This code is running using R notebook in RStudio

The Problem

Water is very important to the continuity of life and is one of the six essential nutrients (carbohydrates, protein, fat, vitamins, and minerals). Approximately 70% of the plants are covered with water, but only 2.5% are suitable for drinking or cultivation. As humans use more water, it’s getting harder to find water for consumption, whether it’s because of fertilizers, industrial pollution, or excessive usage of water, which causes the groundwater reservoirs in densely populated cities to shrink. And with increasing population density, we need more water and food, so one of the solutions is water desalination to make it potable. In order to assess quality Potability , which is the suitability of water for human consumption, we need quality measurements and assessments.

Goals:

We are collecting a dataset on water quality to train a machine learning model for binary classification: determining whether water is safe for consumption (1) or not (0). This model will help with water treatment decisions and ensure compliance with quality standards. We applied different Summarzition and plotting methods to help us to understand our dataset, such as scatter, histogram and bar plot. Then, we applyed preprocess in our data using data cleaning, data transformation and feature selection.

Classification and Clustering Goal:

1-classification in this dataset is to build a predictive model that can classify water samples into two categories: potable (suitable for consumption) or non-potable (not suitable for consumption).

2-clustering in this dataset is to identify natural groupings or clusters within the water samples based on their quality parameters.

Data

Source of the dataset:

Kaggle

Information about the dataset

it is contains 10 attributes, 3276 objects, and the class label for our dataset is Potability.

Attribute information

Attribute Description Data Type Possible Values
ph pH level of water decimal 0-14
Hardness Water hardness in water decimal 47.4-323
Solids Dissolved solids in water decimal 321-61.2k
Chloramines Chloramines concentration decimal 0.35-13.1
Sulfate Sulfate concentration decimal 129-481
Conductivity Electrical conductivity decimal 181-753
Organic_carbon Organic carbon content decimal 2.2-28.3
Trihalomethanes Trihalomethanes concentration decimal 0.74-124
Turbidity Turbidity level decimal 1.45-6.74
Potability Indicates water potability boolean 0-1

Library:

#install.packages("caret")
#install.packages("glmnet")
#install.packages("Boruta")
#install.packages("mlbench")
#install.packages("randomForest")
library(cluster)
library(factoextra) 
library(outliers)
library(dplyr)
library(mlbench)
library(caret)
library(glmnet)
library(Boruta)
library(ggplot2)
library(randomForest)
library(pROC)
library(e1071)
library(caret)
library(party)
library(partykit)
library(RWeka)
library(C50)
library(printr)
library(rpart)
library(rpart.plot)

getwd()
[1] "/Users/mahayie/Documents/GitHub/DM1Project"
#setwd("/Users/mahayie/Documents/GitHub/DM1Project")
water_potability = read.csv('Dataset/water_potability.csv')

str(water_potability)
'data.frame':   3276 obs. of  10 variables:
 $ ph             : num  NA 3.72 8.1 8.32 9.09 ...
 $ Hardness       : num  205 129 224 214 181 ...
 $ Solids         : num  20791 18630 19910 22018 17979 ...
 $ Chloramines    : num  7.3 6.64 9.28 8.06 6.55 ...
 $ Sulfate        : num  369 NA NA 357 310 ...
 $ Conductivity   : num  564 593 419 363 398 ...
 $ Organic_carbon : num  10.4 15.2 16.9 18.4 11.6 ...
 $ Trihalomethanes: num  87 56.3 66.4 100.3 32 ...
 $ Turbidity      : num  2.96 4.5 3.06 4.63 4.08 ...
 $ Potability     : int  0 0 0 0 0 0 0 0 0 0 ...

sample of data

sample of raw dataset(first 10 rows):


head(water_potability,10)

sample of raw dataset(last 10 rows):

tail(water_potability, 10)

Five number summary of each attribute in our dataset:

summary(water_potability)
       ph            Hardness          Solids         Chloramines        Sulfate       Conductivity   Organic_carbon 
 Min.   : 0.000   Min.   : 47.43   Min.   :  320.9   Min.   : 0.352   Min.   :129.0   Min.   :181.5   Min.   : 2.20  
 1st Qu.: 6.093   1st Qu.:176.85   1st Qu.:15666.7   1st Qu.: 6.127   1st Qu.:307.7   1st Qu.:365.7   1st Qu.:12.07  
 Median : 7.037   Median :196.97   Median :20927.8   Median : 7.130   Median :333.1   Median :421.9   Median :14.22  
 Mean   : 7.081   Mean   :196.37   Mean   :22014.1   Mean   : 7.122   Mean   :333.8   Mean   :426.2   Mean   :14.28  
 3rd Qu.: 8.062   3rd Qu.:216.67   3rd Qu.:27332.8   3rd Qu.: 8.115   3rd Qu.:360.0   3rd Qu.:481.8   3rd Qu.:16.56  
 Max.   :14.000   Max.   :323.12   Max.   :61227.2   Max.   :13.127   Max.   :481.0   Max.   :753.3   Max.   :28.30  
 NA's   :491                                                          NA's   :781                                    
 Trihalomethanes     Turbidity       Potability    
 Min.   :  0.738   Min.   :1.450   Min.   :0.0000  
 1st Qu.: 55.845   1st Qu.:3.440   1st Qu.:0.0000  
 Median : 66.622   Median :3.955   Median :0.0000  
 Mean   : 66.396   Mean   :3.967   Mean   :0.3901  
 3rd Qu.: 77.337   3rd Qu.:4.500   3rd Qu.:1.0000  
 Max.   :124.000   Max.   :6.739   Max.   :1.0000  
 NA's   :162                                       

Sample of Water_potability dataset

This is a sample of the dataset to help to understand how it is structured and organized

sample(water_potability)

Number of column and rows

dim(water_potability)
[1] 3276   10

Checking for missing values:

The absence of data in certain variables or columns in a dataset is referred to as missing or null values due to various reasons. It can have a negative impact on the dataset’s efficiency and the information that can be taken from it later, so we checked to see whether our data had missing or null values and eliminated these rows to produce a more efficient dataset.

first we checked for missing value to ensures accurate statistics, reliable visualizations, and guides decisions on imputation or removal of missing data.

dim(water_potability)
[1] 3276   10
sum(is.na(water_potability))
[1] 1434

Remove rows with missing values

colSums(is.na(water_potability))
             ph        Hardness          Solids     Chloramines         Sulfate    Conductivity  Organic_carbon 
            491               0               0               0             781               0               0 
Trihalomethanes       Turbidity      Potability 
            162               0               0 
water_potability = na.omit(water_potability)

Second remove NA rows

colSums(is.na(water_potability))
             ph        Hardness          Solids     Chloramines         Sulfate    Conductivity  Organic_carbon 
              0               0               0               0               0               0               0 
Trihalomethanes       Turbidity      Potability 
              0               0               0 

Statistical Measures:

In the given code, you’ve used the summary function to obtain key statistical measures for variables such as “Conductivity,” “Organic_carbon,” “Hardness,” etc., in the water_potability dataset. These measures include minimum, 1st quartile, median, mean, 3rd quartile, and maximum values, offering a succinct overview of each variable’s distribution and characteristics. This provides essential insights for the initial exploration and understanding of the dataset.

With using minimum, maximum, mean, median laws it helps to provide an overview of the data’s key characteristics

summary(water_potability$Conductivity)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  201.6   366.7   423.5   426.5   482.4   753.3 
summary(water_potability$Organic_carbon)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
   2.20   12.12   14.32   14.36   16.68   27.01 
summary(water_potability$Hardness)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  73.49  176.74  197.19  195.97  216.44  317.34 
summary(water_potability$Solids)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  320.9 15615.7 20933.5 21917.4 27182.6 56488.7 
summary(water_potability$Chloramines)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  1.391   6.139   7.144   7.134   8.110  13.127 
summary(water_potability$Potability)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
 0.0000  0.0000  0.0000  0.4033  1.0000  1.0000 
summary(water_potability$Sulfate)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  129.0   307.6   332.2   333.2   359.3   481.0 
summary(water_potability$Trihalomethanes)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  8.577  55.953  66.542  66.401  77.292 124.000 
summary(water_potability$Turbidity)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  1.450   3.443   3.968   3.970   4.514   6.495 
summary(water_potability$ph)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
 0.2275  6.0897  7.0273  7.0860  8.0530 14.0000 

Data Preprocessing :

Data Transformation:

The process of converting or modifying raw data into a different format or structure to make it more suitable for analysis or modeling

This step involved transforming the class label, Potability, into categorical data. We changed the numeric data to ‘Not Potable’ and ‘Potable’ to indicate whether the water is safe for human consumption, where 1 represents ‘Potable’, and 0 represents ’Not Potable.

water_potability$Potability[water_potability$Potability == '0'] <- 'Not Potable'
water_potability$Potability[water_potability$Potability == '1'] <- 'Potable'

water_potability$Potability <- as.factor(water_potability$Potability)
table(water_potability$Potability)

Not Potable     Potable 
       1200         811 
print(water_potability)

the ROSE package to address class imbalance in a binary classification scenario with a ‘Potability’ target variable. The code converts ‘Potability’ to a factor, performs oversampling on the minority class using the ovun.sample function, and displays the balanced dataset alongside the original for a comparison of class distributions. This preprocessing step enhances model generalization by ensuring better representation of the minority class during training. The oversampling is applied to all features except the target variable.

Outliers:

They are observations that lie far away from the majority of the data. Outliers can occur due to various reasons such as measurement errors, experimental anomalies, or genuine extreme values.

before removing outlier:

dim(water_potability)
[1] 2011   10
head(water_potability)

removing outliers:

Removing outliers from a dataset is critical for assuring the quality and reliability of statistical analysis and machine learning models. We found all outliers in the numerical attributes and subsequently eliminated the rows containing the outliers.

-ph

summary(water_potability$ph)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
 0.2275  6.0897  7.0273  7.0860  8.0530 14.0000 
quartiles <- quantile(water_potability$ph, probs = c(.25, .75), na.rm = FALSE)
quartiles
     25%      75% 
6.089723 8.052969 
iqr <- IQR(water_potability$ph)
iqr
[1] 1.963245
lower <- quartiles[1] - 1.5*iqr
lower
     25% 
3.144855 
upper <- quartiles[2] + 1.5*iqr
upper
     75% 
10.99784 
boxplot(ph ~ Potability, data = water_potability)


repeat {
  out_val <- boxplot(water_potability$ph, ylab = 'ph')$out
  out_val
  out_rows <- which(water_potability$ph %in% c(out_val))
  out_rows
  
  if(sum(out_rows) > 0) water_potability <- water_potability[-out_rows,]
  else {break}
}

summary(water_potability$ph)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  3.231   6.105   7.027   7.087   8.030  10.905 
#-------------------------------------------

-Hardness

summary(water_potability$Hardness)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  73.49  176.90  197.36  196.27  216.44  317.34 
quartiles <- quantile(water_potability$Hardness, probs = c(.25, .75), na.rm = FALSE)
quartiles
     25%      75% 
176.9031 216.4411 
iqr <- IQR(water_potability$Hardness)
iqr
[1] 39.53799
lower <- quartiles[1] - 1.5*iqr
lower
     25% 
117.5961 
upper <- quartiles[2] + 1.5*iqr
upper
     75% 
275.7481 
boxplot(Hardness ~ Potability, data = water_potability)


repeat {
  out_val <- boxplot(water_potability$Hardness, ylab = 'Hardness')$out
  out_val
  out_rows <- which(water_potability$Hardness %in% c(out_val))
  out_rows

  if(sum(out_rows) > 0) water_potability <- water_potability[-out_rows,]
  else {break}
}

summary(water_potability$Hardness)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  121.0   177.7   197.3   196.2   215.5   272.1 
#-------------------------------------------

-Solids

summary(water_potability$Solids)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  320.9 15704.5 20855.3 21840.2 27045.9 56488.7 
quartiles <- quantile(water_potability$Solids, probs = c(.25, .75), na.rm = FALSE)
quartiles
     25%      75% 
15704.48 27045.93 
iqr <- IQR(water_potability$Solids)
iqr
[1] 11341.45
lower <- quartiles[1] - 1.5*iqr
lower
     25% 
-1307.69 
upper <- quartiles[2] + 1.5*iqr
upper
    75% 
44058.1 
boxplot(Solids ~ Potability, data = water_potability)


repeat {
  out_val <- boxplot(water_potability$Solids, ylab = 'Solids')$out
  out_val
  out_rows <- which(water_potability$Solids %in% c(out_val))
  out_rows

  if(sum(out_rows) > 0) water_potability <- water_potability[-out_rows,]
  else {break}
}

summary(water_potability$Solids)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  320.9 15547.5 20518.7 21419.6 26734.7 43195.5 
#-------------------------------------------

-Chloramines

summary(water_potability$Chloramines)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  1.391   6.141   7.135   7.135   8.094  13.127 
quartiles <- quantile(water_potability$Chloramines, probs = c(.25, .75), na.rm = FALSE)
quartiles
     25%      75% 
6.141236 8.094323 
iqr <- IQR(water_potability$Chloramines)
iqr
[1] 1.953087
lower <- quartiles[1] - 1.5*iqr
lower
     25% 
3.211605 
upper <- quartiles[2] + 1.5*iqr
upper
     75% 
11.02395 
boxplot(Chloramines ~ Potability, data = water_potability)


repeat {
  out_val <- boxplot(water_potability$Chloramines, ylab = 'Chloramines')$out
  out_val
  out_rows <- which(water_potability$Chloramines %in% c(out_val))
  out_rows

  if(sum(out_rows) > 0) water_potability <- water_potability[-out_rows,]
  else {break}
}

summary(water_potability$Chloramines)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  3.352   6.181   7.137   7.136   8.076  10.897 
#-------------------------------------------

-Sulfate

summary(water_potability$Sulfate)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  187.2   308.2   332.6   333.4   358.3   481.0 
quartiles <- quantile(water_potability$Sulfate, probs = c(.25, .75), na.rm = FALSE)
quartiles
     25%      75% 
308.1884 358.3020 
iqr <- IQR(water_potability$Sulfate)
iqr
[1] 50.11358
lower <- quartiles[1] - 1.5*iqr
lower
     25% 
233.0181 
upper <- quartiles[2] + 1.5*iqr
upper
     75% 
433.4724 
boxplot(Sulfate ~ Potability, data = water_potability)


repeat {
  out_val <- boxplot(water_potability$Sulfate, ylab = 'Sulfate')$out
  out_val
  out_rows <- which(water_potability$Sulfate %in% c(out_val))
  out_rows

  if(sum(out_rows) > 0) water_potability <- water_potability[-out_rows,]
  else {break}
}

summary(water_potability$Sulfate)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  237.5   309.2   332.8   333.6   357.7   429.8 
#-------------------------------------------

-Conductivity

summary(water_potability$Conductivity)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  201.6   366.6   423.6   426.8   482.6   753.3 
quartiles <- quantile(water_potability$Conductivity, probs = c(.25, .75), na.rm = FALSE)
quartiles
     25%      75% 
366.5581 482.5983 
iqr <- IQR(water_potability$Conductivity)
iqr
[1] 116.0401
lower <- quartiles[1] - 1.5*iqr
lower
     25% 
192.4979 
upper <- quartiles[2] + 1.5*iqr
upper
     75% 
656.6585 
boxplot(Conductivity ~ Potability, data = water_potability)


repeat {
  out_val <- boxplot(water_potability$Conductivity, ylab = 'Conductivity')$out
  out_val
  out_rows <- which(water_potability$Conductivity %in% c(out_val))
  out_rows

  if(sum(out_rows) > 0) water_potability <- water_potability[-out_rows,]
  else {break}
}

summary(water_potability$Conductivity)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  201.6   366.4   423.1   426.0   481.9   652.5 
#-------------------------------------------

-Organic_carbon

summary(water_potability$Organic_carbon)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  4.372  12.184  14.351  14.417  16.788  27.007 
quartiles <- quantile(water_potability$Organic_carbon, probs = c(.25, .75), na.rm = FALSE)
quartiles
     25%      75% 
12.18447 16.78779 
iqr <- IQR(water_potability$Organic_carbon)
iqr
[1] 4.603315
lower <- quartiles[1] - 1.5*iqr
lower
     25% 
5.279502 
upper <- quartiles[2] + 1.5*iqr
upper
     75% 
23.69276 
boxplot(Organic_carbon ~ Potability, data = water_potability)


repeat {
  out_val <- boxplot(water_potability$Organic_carbon, ylab = 'Organic_carbon')$out
  out_val
  out_rows <- which(water_potability$Organic_carbon %in% c(out_val))
  out_rows

  if(sum(out_rows) > 0) water_potability <- water_potability[-out_rows,]
  else {break}
}

summary(water_potability$Organic_carbon)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  5.512  12.222  14.352  14.426  16.786  23.604 
#-------------------------------------------

-Trihalomethanes

summary(water_potability$Trihalomethanes)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  8.577  55.865  66.231  66.364  77.418 124.000 
quartiles <- quantile(water_potability$Trihalomethanes, probs = c(.25, .75), na.rm = FALSE)
quartiles
     25%      75% 
55.86494 77.41789 
iqr <- IQR(water_potability$Trihalomethanes)
iqr
[1] 21.55295
lower <- quartiles[1] - 1.5*iqr
lower
     25% 
23.53552 
upper <- quartiles[2] + 1.5*iqr
upper
     75% 
109.7473 
boxplot(Trihalomethanes ~ Potability, data = water_potability)


repeat {
  out_val <- boxplot(water_potability$Trihalomethanes, ylab = 'Trihalomethanes')$out
  out_val
  out_rows <- which(water_potability$Trihalomethanes %in% c(out_val))
  out_rows

  if(sum(out_rows) > 0) water_potability <- water_potability[-out_rows,]
  else {break}
}

summary(water_potability$Trihalomethanes)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  24.53   55.96   66.29   66.42   77.34  108.85 
#-------------------------------------------

-Turbidity

summary(water_potability$Turbidity)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  1.450   3.441   3.975   3.973   4.519   6.495 
quartiles <- quantile(water_potability$Turbidity, probs = c(.25, .75), na.rm = FALSE)
quartiles
     25%      75% 
3.440859 4.518751 
iqr <- IQR(water_potability$Turbidity)
iqr
[1] 1.077892
lower <- quartiles[1] - 1.5*iqr
lower
     25% 
1.824021 
upper <- quartiles[2] + 1.5*iqr
upper
     75% 
6.135588 
boxplot(Turbidity ~ Potability, data = water_potability)


repeat {
  out_val <- boxplot(water_potability$Turbidity, ylab = 'Turbidity')$out
  out_val
  out_rows <- which(water_potability$Turbidity %in% c(out_val))
  out_rows

  if(sum(out_rows) > 0) water_potability <- water_potability[-out_rows,]
  else {break}
}

summary(water_potability$Turbidity)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  1.873   3.443   3.974   3.972   4.512   6.084 

After removing outliers:

dim(water_potability)
[1] 1750   10
str(water_potability)
'data.frame':   1750 obs. of  10 variables:
 $ ph             : num  8.32 9.09 5.58 10.22 8.64 ...
 $ Hardness       : num  214 181 188 248 203 ...
 $ Solids         : num  22018 17979 28749 28750 13672 ...
 $ Chloramines    : num  8.06 6.55 7.54 7.51 4.56 ...
 $ Sulfate        : num  357 310 327 394 303 ...
 $ Conductivity   : num  363 398 280 284 475 ...
 $ Organic_carbon : num  18.4 11.6 8.4 13.8 12.4 ...
 $ Trihalomethanes: num  100.3 32 54.9 84.6 62.8 ...
 $ Turbidity      : num  4.63 4.08 2.56 2.67 4.4 ...
 $ Potability     : Factor w/ 2 levels "Not Potable",..: 1 1 1 1 1 1 1 1 1 1 ...
 - attr(*, "na.action")= 'omit' Named int [1:1265] 1 2 3 9 12 14 15 17 19 21 ...
  ..- attr(*, "names")= chr [1:1265] "1" "2" "3" "9" ...
head(water_potability)

Checking for imbalanced dataset:

class_distribution <- table(water_potability$Potability)
print(class_distribution)

Not Potable     Potable 
       1066         684 
# Check if the dataset is balanced
is_balanced <- diff(class_distribution) == 0
if (is_balanced) {
  print("The dataset is balanced.")
} else {
  print("The dataset is imbalanced.")
}
[1] "The dataset is imbalanced."
boxplot(water_potability$ph, ylab = 'ph')$out
[1] 10.90508 10.81129 10.89348 10.81783 10.80816

boxplot(water_potability$Chloramines, ylab = 'Chloramines')$out
[1]  3.351598  3.372369 10.896663

boxplot(water_potability$Hardness, ylab = 'Hardness')$out
[1] 121.4414 271.6308 121.5751 271.6012 121.0363 272.1117

boxplot(water_potability$Solids, ylab = 'Solids')$out
numeric(0)

boxplot(water_potability$Sulfate, ylab = 'Sulfate')$out
numeric(0)

boxplot(water_potability$Conductivity, ylab = 'Conductivity')$out
numeric(0)

boxplot(water_potability$Organic_carbon, ylab = 'Organic_carbon')$out
numeric(0)

boxplot(water_potability$Trihalomethanes, ylab = 'Trihalomethanes')$out
numeric(0)

boxplot(water_potability$Turbidity, ylab = 'Turbidity')$out
numeric(0)

Charts:

visual representation of data that help us understand and analyze information more easily. They can be used to display trends, comparisons, and relationships between different variables. There are various types of charts, such as

Histogram

The histogram shows the frequency of ph in the dataset; we noted that the majority of values fall within the usual range, which is about between 6 and 8, but it also shows several outliers.

hist(water_potability$ph)

hist(water_potability$Chloramines)

hist(water_potability$Hardness)

hist(water_potability$Solids)

hist(water_potability$Sulfate)

hist(water_potability$Conductivity)

hist(water_potability$Organic_carbon)

hist(water_potability$Trihalomethanes)

hist(water_potability$Turbidity)

Bar Plot

the bar plot represent how ph levels affect water portability in the dataset it indicates that ph level above 10 is not portibal and humans cant consume it

tab <- water_potability$Potability %>% table()
txt <- paste0(tab) 
bb <- water_potability$ph %>% table() %>% barplot( main='ph',col=c('pink'))

bb <- water_potability$Potability %>% table() %>% barplot( main='Potability',ylab='Frequency',col=c('pink', 'lightblue'))
text(bb, tab/2, labels=txt, cex=1)

Scatter Plot

This scatter demonstrates the correlation and proportionality between the two qualities, allowing us to establish whether or not turbidity and pH are connected.

with(water_potability, plot(Trihalomethanes, ph, col = Potability, pch = as.numeric(Potability)))

Remove Redundant Features:

This will find the correlation between the features and represent it in heatmap

correlation_matrix <- cor(water_potability[,1:9])
high_correlation_features <- findCorrelation(correlation_matrix, cutoff = 0.5)
print(high_correlation_features)
integer(0)

Heatmap:

A powerful visualization tool that allows for a quick and intuitive interpretation of the relationships between numeric variables. It provides valuable insights into the structure and dependencies within your dataset.

heatmap(correlation_matrix)

we remove the correlation between the features and represent it in heat map

Feature selection:

Rank Features By Importance:

ranking features by importance is a technique used to identify the most influential variables in a dataset for predicting a target variable. This process helps in understanding which features have the most impact on the model’s performance. By ranking features by importance.

#train random forest model and calculate feature importance
rf = randomForest(x= water_potability[,1:9],y= water_potability[,10])
var_imp <- varImp(rf, scale = FALSE)
#sort the score in decreasing order
var_imp_df <- data.frame(cbind(variable = rownames(var_imp), score = var_imp[,1]))
var_imp_df$score <- as.double(var_imp_df$score)
var_imp_df[order(var_imp_df$score,decreasing = TRUE),]

ggplot(var_imp_df, aes(x=reorder(variable, score), y=score)) + 
  geom_point() +
  geom_segment(aes(x=variable,xend=variable,y=0,yend=score)) +
  ylab("IncNodePurity") +
  xlab("Variable Name") +
  coord_flip()

Recursive Feature elimination:

is a feature selection technique that recursively removes less important features from a model until the optimal subset is identified. It involves repeatedly training the model, ranking features based on their importance, and eliminating the least important ones.

set.seed(1958)
control <- rfeControl(functions=rfFuncs, method="cv",number=10)
# run the RFE algorithm 
rfe_model <- rfe(x= water_potability[,1:9],y= water_potability[,10], sizes=c(1:9), rfeControl=control) 
# summarize the results 
print(rfe_model) 

Recursive feature selection

Outer resampling method: Cross-Validated (10 fold) 

Resampling performance over subset size:

The top 5 variables (out of 5):
   Sulfate, ph, Hardness, Solids, Chloramines
# list the chosen features 
predictors(rfe_model) 
[1] "Sulfate"     "ph"          "Hardness"    "Solids"      "Chloramines"
# plot the results 
plot(rfe_model, type=c("g", "o"))

Normlization

Normalization refers to the process of scaling variables to have a common range. It helps in comparing variables with different scales.

wp<- water_potability
normalize=function(x){return ((x-min(x))/(max(x)))}
wp$Solids=normalize(wp$Solids)

The solids attribute will create critical challenges because of the vast and diverted values: min is 320.9, and max is 43195.5, so we normalized the solids between 0 and 1 to make values smaller and more reasonable.

Discretization:

Discretization is the process of transforming continuous variables into discrete or categorical variables. It can be useful for analyzing data with many unique values or simplifying it.


wp$ph= cut(wp$ph, breaks = seq(3,11,by=4),right=FALSE)
wp$Hardness= cut(wp$Hardness, breaks = seq(120,280,by=40),right=FALSE)
wp$Chloramines = cut(wp$Chloramines, breaks = seq(3,11,by=4),right = FALSE)
wp$Sulfate= cut(wp$Sulfate, breaks = seq(220,440,by=44),right=FALSE)
wp$Conductivity= cut(wp$Conductivity, breaks = seq(200,700,by=100),right=FALSE)
wp$Organic_carbon= cut(wp$Organic_carbon, breaks = seq(4,24,by=4),right=FALSE)
wp$Trihalomethanes= cut(wp$Trihalomethanes, breaks = seq(20,110,by=10),right=FALSE)
wp$Turbidity= cut(wp$Turbidity, breaks = seq(1,7,by=2),right=FALSE)

print(wp)

Therefore, we transformed the continuous values of the numeric attributes into intervals by dividing the values to fall on one of the possible interval labels by discretization. The values will be meaningful and simpler to classify or perform other methods to help us later in our model. So, In Trihalomethanes, we intervals by dividing the values by 10 to have labels with equal width : [20,30) [30,40) [40,50) [50,60) [60,70) [70,80) [80,90) [90,100) [100,110).

Encoding

encoding is the process of converting characters or strings into a specific encoding format. Since we don’t have a Nominal attribute in our database we couldn’t implement it.

wp

Classfication and Clustring

In our dataset exploration, we employed both supervised and unsupervised learning methodologies through classification and clustering techniques.

For classification, we chose the decision tree algorithm, a recursive approach constructing a tree structure with leaf nodes signifying final decisions. The objective was to predict the class label (potability), with values 0 or 1, based on attributes like pH, Hardness, Solids, Chloramines, Sulfate, Conductivity, Organic_carbon, Trihalomethanes, and Turbidity. The dataset underwent division into training and testing sets for constructing and evaluating the decision tree. Model evaluation encompassed metrics like accuracy and cost-sensitive measures, gauged using a confusion matrix. Our toolkit included packages such as ‘party’ and ‘caret,’ incorporating methods like ‘sample’ for data splitting, ‘ctree’ for decision tree construction, ‘predict’ for testing predictions, and ‘confusionMatrix’ for model evaluation.

In the unsupervised clustering phase, we excluded the class label attribute “potability” and utilized numeric attributes such as pH, Hardness, Solids, Chloramines, Sulfate, Conductivity, Organic_carbon, Trihalomethanes, and Turbidity. Employing the K-means algorithm, clusters were formed, each represented by a center point, and objects were assigned to the nearest cluster. For this phase, we made use of packages such as ‘cluster’ and ‘factoextra,’ incorporating methods like ‘scale()’ for data scaling, ‘Kmeans()’ for cluster creation.

Cluster validation was performed using the ‘silhouette()’ method to calculate averages for each cluster. In both supervised and unsupervised techniques, we maintained result consistency by employing the ‘set.seed()’ method with the same random number when experimenting with different dataset sizes.

Training technique

In the provided code, we systematically addressed outliers in multiple columns of our dataset. Beginning with a summary of each column’s statistics, including quartiles and the interquartile range (IQR), we established outlier detection limits. A visual assessment was conducted using boxplots, categorized by relevant variables such as “Potability.” A loop was implemented to iteratively identify and remove outliers in each column, ensuring a robust cleansing process. The final step involved summarizing the columns post-outlier removal, offering insights into the impact on the distribution of each variable. This comprehensive approach was applied uniformly to all dataset columns, promoting consistency in the outlier-handling process.

Evaluation and Comparison

Information gain (ID3)

In this R code, the dataset undergoes a process of training and testing using the ID3 algorithm for decision tree classification. The data is successively split into training sets of 70%, 80%, and 90%, with corresponding testing sets of 30%, 20%, and 10%. The decision tree models are trained on these subsets, utilizing features such as pH, hardness, solids, chloramines, sulfate, conductivity, organic carbon, trihalomethanes, and turbidity to predict water potability.

For each split, the decision tree models are evaluated on their respective testing sets, and performance metrics such as confusion matrices and accuracy are computed. Additionally, Receiver Operating Characteristic (ROC) curves are generated, providing insights into the models’ discrimination capabilities. The Area Under the Curve (AUC) is calculated as a quantitative measure of model performance. This comprehensive approach enables a systematic exploration of the ID3 decision tree’s effectiveness in predicting water potability under varying training and testing scenarios.

Splitting the data set into two subsets: Training(70%) and Testing(30%):

set.seed(1958)
ind <- sample(2, nrow(wp), replace = TRUE, prob = c(0.7, 0.3))
train.data <- wp[ind == 1, ]
test.data <- wp[ind == 2, ]
train.data$Potability <- as.factor(train.data$Potability)
test.data$Potability <- as.factor(test.data$Potability)


myFormula <- Potability ~ ph+Hardness+Solids+Chloramines+Sulfate+Conductivity+Organic_carbon+Trihalomethanes+Turbidity
#myFormula <- Potability ~ ph+Hardness+Solids+Chloramines+Sulfate


m.ctree <- ctree(myFormula, data = train.data)
table(predict(m.ctree), train.data$Potability)
             
              Not Potable Potable
  Not Potable         720     412
  Potable              35      56
print(m.ctree)

Model formula:
Potability ~ ph + Hardness + Solids + Chloramines + Sulfate + 
    Conductivity + Organic_carbon + Trihalomethanes + Turbidity

Fitted party:
[1] root
|   [2] Sulfate in [220,264), [396,440): Potable (n = 91, err = 38.5%)
|   [3] Sulfate in [264,308), [308,352), [352,396): Not Potable (n = 1132, err = 36.4%)

Number of inner nodes:    1
Number of terminal nodes: 2
plot(m.ctree, type="simple")

plot(m.ctree)



testPred <- predict(m.ctree, newdata = test.data)
result<-table(testPred, test.data$Potability)


co_result <- confusionMatrix(result)
print(co_result)
Confusion Matrix and Statistics

             
testPred      Not Potable Potable
  Not Potable         293     200
  Potable              18      16
                                         
               Accuracy : 0.5863         
                 95% CI : (0.543, 0.6287)
    No Information Rate : 0.5901         
    P-Value [Acc > NIR] : 0.5886         
                                         
                  Kappa : 0.0186         
                                         
 Mcnemar's Test P-Value : <2e-16         
                                         
            Sensitivity : 0.94212        
            Specificity : 0.07407        
         Pos Pred Value : 0.59432        
         Neg Pred Value : 0.47059        
             Prevalence : 0.59013        
         Detection Rate : 0.55598        
   Detection Prevalence : 0.93548        
      Balanced Accuracy : 0.50810        
                                         
       'Positive' Class : Not Potable    
                                         
as.matrix(co_result, what = "classes")
                           [,1]
Sensitivity          0.94212219
Specificity          0.07407407
Pos Pred Value       0.59432049
Neg Pred Value       0.47058824
Precision            0.59432049
Recall               0.94212219
F1                   0.72885572
Prevalence           0.59013283
Detection Rate       0.55597723
Detection Prevalence 0.93548387
Balanced Accuracy    0.50809813
acc <- co_result$overall["Accuracy"]
acc*100
Accuracy 
58.63378 
pred_probs <- as.numeric(predict(m.ctree, newdata = test.data, type = "response"))
binary_outcome <- as.numeric(test.data$Potability == "Potable")
# ROC curve
roc_curve <- roc(binary_outcome, pred_probs)
Setting levels: control = 0, case = 1
Setting direction: controls < cases
plot(roc_curve, main = "ROC Curve", col = "blue", lwd = 2)
abline(a = 0, b = 1, col = "gray", lty = 2)

# Print AUC
cat("AUC:", auc(roc_curve), "\n")
AUC: 0.5080981 

Splitting the data set into two subsets: Training(80%) and Testing(20%):


set.seed(1958)
ind <- sample(2, nrow(wp), replace = TRUE, prob = c(0.8, 0.2))
train.data <- wp[ind == 1, ]
test.data <- wp[ind == 2, ]
train.data$Potability <- as.factor(train.data$Potability)

myFormula <- Potability ~ ph+Hardness+Solids+Chloramines+Sulfate+Conductivity+Organic_carbon+Trihalomethanes+Turbidity
#myFormula <- Potability ~ ph+Hardness+Solids+Chloramines+Sulfate


m.ctree <- ctree(myFormula, data = train.data)
table(predict(m.ctree), train.data$Potability)
             
              Not Potable Potable
  Not Potable         854     472
  Potable              12      55
print(m.ctree)

Model formula:
Potability ~ ph + Hardness + Solids + Chloramines + Sulfate + 
    Conductivity + Organic_carbon + Trihalomethanes + Turbidity

Fitted party:
[1] root
|   [2] Sulfate in [220,264), [264,308), [352,396), [396,440)
|   |   [3] Solids <= 0.64014: Not Potable (n = 598, err = 40.1%)
|   |   [4] Solids > 0.64014
|   |   |   [5] Sulfate in [220,264), [264,308)
|   |   |   |   [6] ph in [3,7)
|   |   |   |   |   [7] Chloramines in [3,7): Potable (n = 17, err = 23.5%)
|   |   |   |   |   [8] Chloramines in [7,11): Not Potable (n = 15, err = 20.0%)
|   |   |   |   [9] ph in [7,11): Potable (n = 50, err = 16.0%)
|   |   |   [10] Sulfate in [352,396), [396,440): Not Potable (n = 62, err = 38.7%)
|   [11] Sulfate in [308,352): Not Potable (n = 651, err = 31.5%)

Number of inner nodes:    5
Number of terminal nodes: 6
plot(m.ctree, type="simple")

plot(m.ctree)


testPred <- predict(m.ctree, newdata = test.data)
result<-table(testPred, test.data$Potability)


co_result <- confusionMatrix(result)
print(co_result)
Confusion Matrix and Statistics

             
testPred      Not Potable Potable
  Not Potable         192     144
  Potable               8      13
                                          
               Accuracy : 0.5742          
                 95% CI : (0.5211, 0.6261)
    No Information Rate : 0.5602          
    P-Value [Acc > NIR] : 0.3163          
                                          
                  Kappa : 0.0472          
                                          
 Mcnemar's Test P-Value : <2e-16          
                                          
            Sensitivity : 0.9600          
            Specificity : 0.0828          
         Pos Pred Value : 0.5714          
         Neg Pred Value : 0.6190          
             Prevalence : 0.5602          
         Detection Rate : 0.5378          
   Detection Prevalence : 0.9412          
      Balanced Accuracy : 0.5214          
                                          
       'Positive' Class : Not Potable     
                                          
as.matrix(co_result, what = "classes")
                           [,1]
Sensitivity          0.96000000
Specificity          0.08280255
Pos Pred Value       0.57142857
Neg Pred Value       0.61904762
Precision            0.57142857
Recall               0.96000000
F1                   0.71641791
Prevalence           0.56022409
Detection Rate       0.53781513
Detection Prevalence 0.94117647
Balanced Accuracy    0.52140127
acc <- co_result$overall["Accuracy"]
acc*100
Accuracy 
57.42297 
pred_probs <- as.numeric(predict(m.ctree, newdata = test.data, type = "response"))
binary_outcome <- as.numeric(test.data$Potability == "Potable")
# ROC curve
roc_curve <- roc(binary_outcome, pred_probs)
Setting levels: control = 0, case = 1
Setting direction: controls < cases
plot(roc_curve, main = "ROC Curve", col = "blue", lwd = 2)
abline(a = 0, b = 1, col = "gray", lty = 2)

# Print AUC
cat("AUC:", auc(roc_curve), "\n")
AUC: 0.5214013 

Splitting the data set into two subsets: Training(90%) and Testing(10%):

set.seed(1958)
ind <- sample(2, nrow(wp), replace = TRUE, prob = c(0.9, 0.1))
train.data <- wp[ind == 1, ]
test.data <- wp[ind == 2, ]
train.data$Potability <- as.factor(train.data$Potability)

myFormula <- Potability ~ ph+Hardness+Solids+Chloramines+Sulfate+Conductivity+Organic_carbon+Trihalomethanes+Turbidity
#myFormula <- Potability ~ ph+Hardness+Solids+Chloramines+Sulfate


m.ctree <- ctree(myFormula, data = train.data)
table(predict(m.ctree), train.data$Potability)
             
              Not Potable Potable
  Not Potable         904     501
  Potable              58     110
print(m.ctree)

Model formula:
Potability ~ ph + Hardness + Solids + Chloramines + Sulfate + 
    Conductivity + Organic_carbon + Trihalomethanes + Turbidity

Fitted party:
[1] root
|   [2] Sulfate in [220,264), [264,308), [352,396), [396,440)
|   |   [3] Solids <= 0.66526
|   |   |   [4] Sulfate in [220,264), [396,440): Potable (n = 86, err = 43.0%)
|   |   |   [5] Sulfate in [264,308), [352,396): Not Potable (n = 618, err = 39.6%)
|   |   [6] Solids > 0.66526
|   |   |   [7] Sulfate in [220,264), [264,308): Potable (n = 82, err = 25.6%)
|   |   |   [8] Sulfate in [352,396), [396,440): Not Potable (n = 54, err = 37.0%)
|   [9] Sulfate in [308,352): Not Potable (n = 733, err = 32.2%)

Number of inner nodes:    4
Number of terminal nodes: 5
plot(m.ctree, type="simple")

plot(m.ctree)


testPred <- predict(m.ctree, newdata = test.data)
result<-table(testPred, test.data$Potability)


co_result <- confusionMatrix(result)
print(co_result)
Confusion Matrix and Statistics

             
testPred      Not Potable Potable
  Not Potable          91      64
  Potable              13       9
                                          
               Accuracy : 0.565           
                 95% CI : (0.4885, 0.6392)
    No Information Rate : 0.5876          
    P-Value [Acc > NIR] : 0.7547          
                                          
                  Kappa : -0.0019         
                                          
 Mcnemar's Test P-Value : 1.212e-08       
                                          
            Sensitivity : 0.8750          
            Specificity : 0.1233          
         Pos Pred Value : 0.5871          
         Neg Pred Value : 0.4091          
             Prevalence : 0.5876          
         Detection Rate : 0.5141          
   Detection Prevalence : 0.8757          
      Balanced Accuracy : 0.4991          
                                          
       'Positive' Class : Not Potable     
                                          
as.matrix(co_result, what = "classes")
                          [,1]
Sensitivity          0.8750000
Specificity          0.1232877
Pos Pred Value       0.5870968
Neg Pred Value       0.4090909
Precision            0.5870968
Recall               0.8750000
F1                   0.7027027
Prevalence           0.5875706
Detection Rate       0.5141243
Detection Prevalence 0.8757062
Balanced Accuracy    0.4991438
acc <- co_result$overall["Accuracy"]
acc*100
Accuracy 
56.49718 
pred_probs <- as.numeric(predict(m.ctree, newdata = test.data, type = "response"))
binary_outcome <- as.numeric(test.data$Potability == "Potable")
# ROC curve
roc_curve <- roc(binary_outcome, pred_probs)
Setting levels: control = 0, case = 1
Setting direction: controls < cases
plot(roc_curve, main = "ROC Curve", col = "blue", lwd = 2)
abline(a = 0, b = 1, col = "gray", lty = 2)

# Print AUC
cat("AUC:", auc(roc_curve), "\n")
AUC: 0.4991438 

Gain ratio (C4.5)

a decision tree-based classifier, is utilized for model training and evaluation. The dataset undergoes cross-validation with different fold settings (3 folds, 5 folds, and 10 folds). For each fold configuration, a J48 model is trained, and its predictive performance is assessed using Receiver Operating Characteristic (ROC) curves. The Area Under the Curve is calculated for each ROC curve, providing a quantitative measure of the model’s ability to predict water potability. Notably, the visual inspection of the ROC curves indicates that the model trained with 10-fold cross-validation exhibits the highest discriminative performance. This comparative analysis across various cross-validation scenarios offers valuable insights into the robustness and generalization capability.

# 3 folds
set.seed(1958)
train <- createFolds(wp$Potability, k=3)
C45Fit <- train(Potability ~ .,method = "J48",data = wp,
                trControl = trainControl(
                method = "cv",
                index = train,
                savePredictions = TRUE))

C45Fit
C4.5-like Trees 

1750 samples
   9 predictor
   2 classes: 'Not Potable', 'Potable' 

No pre-processing
Resampling: Cross-Validated (10 fold) 
Summary of sample sizes: 584, 583, 583 
Resampling results across tuning parameters:

  C      M  Accuracy   Kappa     
  0.010  1  0.6140010  0.02242533
  0.010  2  0.6080020  0.05080768
  0.010  3  0.6148589  0.02353259
  0.255  1  0.5865761  0.09696359
  0.255  2  0.5800048  0.08645875
  0.255  3  0.5842866  0.08011865
  0.500  1  0.5548589  0.06529168
  0.500  2  0.5622907  0.07454861
  0.500  3  0.5668601  0.07437164

Accuracy was used to select the optimal model using the largest value.
The final values used for the model were C = 0.01 and M = 3.
summary(C45Fit)

=== Summary ===

Correctly Classified Instances        1088               62.1714 %
Incorrectly Classified Instances       662               37.8286 %
Kappa statistic                          0.045 
Mean absolute error                      0.4692
Root mean squared error                  0.4844
Relative absolute error                 98.5319 %
Root relative squared error             99.266  %
Total Number of Instances             1750     

=== Confusion Matrix ===

    a    b   <-- classified as
 1056   10 |    a = Not Potable
  652   32 |    b = Potable
C45Fit$finalModel
J48 pruned tree
------------------

Sulfate[396,440) <= 0: Not Potable (1670.0/640.0)
Sulfate[396,440) > 0
|   ph[7,11) <= 0: Potable (42.0/10.0)
|   ph[7,11) > 0: Not Potable (38.0/12.0)

Number of Leaves  :     3

Size of the tree :  5
pred_probs <- predict(C45Fit, newdata = wp)
re3<-table(pred_probs ,wp$Potability)

r3 <- confusionMatrix(re3)
acc <- r3$overall["Accuracy"]*100
acc
Accuracy 
62.17143 
as.matrix(r3, what = "classes")
                           [,1]
Sensitivity          0.99061914
Specificity          0.04678363
Pos Pred Value       0.61826698
Neg Pred Value       0.76190476
Precision            0.61826698
Recall               0.99061914
F1                   0.76135544
Prevalence           0.60914286
Detection Rate       0.60342857
Detection Prevalence 0.97600000
Balanced Accuracy    0.51870138
print(r3)
Confusion Matrix and Statistics

             
pred_probs    Not Potable Potable
  Not Potable        1056     652
  Potable              10      32
                                          
               Accuracy : 0.6217          
                 95% CI : (0.5985, 0.6445)
    No Information Rate : 0.6091          
    P-Value [Acc > NIR] : 0.1461          
                                          
                  Kappa : 0.045           
                                          
 Mcnemar's Test P-Value : <2e-16          
                                          
            Sensitivity : 0.99062         
            Specificity : 0.04678         
         Pos Pred Value : 0.61827         
         Neg Pred Value : 0.76190         
             Prevalence : 0.60914         
         Detection Rate : 0.60343         
   Detection Prevalence : 0.97600         
      Balanced Accuracy : 0.51870         
                                          
       'Positive' Class : Not Potable     
                                          
pred_probs <- predict(C45Fit, newdata = wp, type = "prob")[, "Potable"]
binary_outcome <- as.numeric(wp$Potability == "Potable")
# ROC curve
roc_curve <- roc(binary_outcome, pred_probs)
Setting levels: control = 0, case = 1
Setting direction: controls < cases
plot(roc_curve, main = "ROC Curve", col = "blue", lwd = 2)
abline(a = 0, b = 1, col = "gray", lty = 2)

# Print AUC
cat("AUC:", auc(roc_curve), "\n")
AUC: 0.5216363 
# 5 folds
set.seed(1958)
train <- createFolds(wp$Potability, k=5)
C45Fit <- train(Potability ~., method="J48", data=wp,
                trControl = trainControl(
                method ="cv", 
                index = train,
                savePredictions = TRUE))

C45Fit
C4.5-like Trees 

1750 samples
   9 predictor
   2 classes: 'Not Potable', 'Potable' 

No pre-processing
Resampling: Cross-Validated (10 fold) 
Summary of sample sizes: 350, 350, 350, 350, 350 
Resampling results across tuning parameters:

  C      M  Accuracy   Kappa      
  0.010  1  0.6067143  0.003029794
  0.010  2  0.6062857  0.002195738
  0.010  3  0.6060000  0.001633667
  0.255  1  0.5515714  0.030018055
  0.255  2  0.5642857  0.053615393
  0.255  3  0.5667143  0.043028830
  0.500  1  0.5450000  0.036774387
  0.500  2  0.5545714  0.051996482
  0.500  3  0.5527143  0.030952302

Accuracy was used to select the optimal model using the largest value.
The final values used for the model were C = 0.01 and M = 1.
summary(C45Fit)

=== Summary ===

Correctly Classified Instances        1088               62.1714 %
Incorrectly Classified Instances       662               37.8286 %
Kappa statistic                          0.045 
Mean absolute error                      0.4692
Root mean squared error                  0.4844
Relative absolute error                 98.5319 %
Root relative squared error             99.266  %
Total Number of Instances             1750     

=== Confusion Matrix ===

    a    b   <-- classified as
 1056   10 |    a = Not Potable
  652   32 |    b = Potable
C45Fit$finalModel
J48 pruned tree
------------------

Sulfate[396,440) <= 0: Not Potable (1670.0/640.0)
Sulfate[396,440) > 0
|   ph[7,11) <= 0: Potable (42.0/10.0)
|   ph[7,11) > 0: Not Potable (38.0/12.0)

Number of Leaves  :     3

Size of the tree :  5
pred_probs <- predict(C45Fit, newdata = wp)
re5<-table(pred_probs ,wp$Potability)

r5 <- confusionMatrix(re5)
acc <- r5$overall["Accuracy"]*100
acc
Accuracy 
62.17143 
as.matrix(r5, what = "classes")
                           [,1]
Sensitivity          0.99061914
Specificity          0.04678363
Pos Pred Value       0.61826698
Neg Pred Value       0.76190476
Precision            0.61826698
Recall               0.99061914
F1                   0.76135544
Prevalence           0.60914286
Detection Rate       0.60342857
Detection Prevalence 0.97600000
Balanced Accuracy    0.51870138
print(r5)
Confusion Matrix and Statistics

             
pred_probs    Not Potable Potable
  Not Potable        1056     652
  Potable              10      32
                                          
               Accuracy : 0.6217          
                 95% CI : (0.5985, 0.6445)
    No Information Rate : 0.6091          
    P-Value [Acc > NIR] : 0.1461          
                                          
                  Kappa : 0.045           
                                          
 Mcnemar's Test P-Value : <2e-16          
                                          
            Sensitivity : 0.99062         
            Specificity : 0.04678         
         Pos Pred Value : 0.61827         
         Neg Pred Value : 0.76190         
             Prevalence : 0.60914         
         Detection Rate : 0.60343         
   Detection Prevalence : 0.97600         
      Balanced Accuracy : 0.51870         
                                          
       'Positive' Class : Not Potable     
                                          
pred_probs <- predict(C45Fit, newdata = wp, type = "prob")[, "Potable"]
binary_outcome <- as.numeric(wp$Potability == "Potable")
# ROC curve
roc_curve <- roc(binary_outcome, pred_probs)
Setting levels: control = 0, case = 1
Setting direction: controls < cases
plot(roc_curve, main = "ROC Curve", col = "blue", lwd = 2)
abline(a = 0, b = 1, col = "gray", lty = 2)

# Print AUC
cat("AUC:", auc(roc_curve), "\n")
AUC: 0.5216363 
# 10 folds
set.seed(1958)

train <- createFolds(wp$Potability, k=10)
C45Fit <- train(Potability ~., method="J48", data=wp,
                trControl = trainControl(
                  method="cv", indexOut=train))

C45Fit
C4.5-like Trees 

1750 samples
   9 predictor
   2 classes: 'Not Potable', 'Potable' 

No pre-processing
Resampling: Cross-Validated (10 fold) 
Summary of sample sizes: 1576, 1574, 1575, 1574, 1574, 1575, ... 
Resampling results across tuning parameters:

  C      M  Accuracy   Kappa     
  0.010  1  0.6331355  0.08610946
  0.010  2  0.6371355  0.10006932
  0.010  3  0.6359927  0.09906518
  0.255  1  0.8160390  0.59246265
  0.255  2  0.7834603  0.51920580
  0.255  3  0.7611579  0.47221105
  0.500  1  0.8908616  0.76673013
  0.500  2  0.8320196  0.63983987
  0.500  3  0.8006036  0.57209792

Accuracy was used to select the optimal model using the largest value.
The final values used for the model were C = 0.5 and M = 1.
summary(C45Fit)

=== Summary ===

Correctly Classified Instances        1614               92.2286 %
Incorrectly Classified Instances       136                7.7714 %
Kappa statistic                          0.8346
Mean absolute error                      0.1243
Root mean squared error                  0.2493
Relative absolute error                 26.0948 %
Root relative squared error             51.0846 %
Total Number of Instances             1750     

=== Confusion Matrix ===

    a    b   <-- classified as
 1023   43 |    a = Not Potable
   93  591 |    b = Potable
C45Fit$finalModel
J48 pruned tree
------------------

Sulfate[396,440) <= 0
|   Sulfate[308,352) <= 0
|   |   Trihalomethanes[40,50) <= 0
|   |   |   Organic_carbon[20,24) <= 0
|   |   |   |   ph[7,11) <= 0
|   |   |   |   |   Sulfate[352,396) <= 0
|   |   |   |   |   |   Trihalomethanes[70,80) <= 0
|   |   |   |   |   |   |   Turbidity[3,5) <= 0
|   |   |   |   |   |   |   |   Trihalomethanes[30,40) <= 0
|   |   |   |   |   |   |   |   |   Trihalomethanes[90,100) <= 0
|   |   |   |   |   |   |   |   |   |   Chloramines[7,11) <= 0
|   |   |   |   |   |   |   |   |   |   |   Organic_carbon[16,20) <= 0
|   |   |   |   |   |   |   |   |   |   |   |   Solids <= 0.397137: Not Potable (2.0)
|   |   |   |   |   |   |   |   |   |   |   |   Solids > 0.397137: Potable (5.0)
|   |   |   |   |   |   |   |   |   |   |   Organic_carbon[16,20) > 0: Not Potable (2.0)
|   |   |   |   |   |   |   |   |   |   Chloramines[7,11) > 0: Not Potable (14.0/1.0)
|   |   |   |   |   |   |   |   |   Trihalomethanes[90,100) > 0
|   |   |   |   |   |   |   |   |   |   Chloramines[7,11) <= 0: Not Potable (1.0)
|   |   |   |   |   |   |   |   |   |   Chloramines[7,11) > 0: Potable (3.0)
|   |   |   |   |   |   |   |   Trihalomethanes[30,40) > 0: Potable (2.0)
|   |   |   |   |   |   |   Turbidity[3,5) > 0
|   |   |   |   |   |   |   |   Trihalomethanes[80,90) <= 0
|   |   |   |   |   |   |   |   |   Hardness[240,280) <= 0
|   |   |   |   |   |   |   |   |   |   Sulfate[264,308) <= 0
|   |   |   |   |   |   |   |   |   |   |   Hardness[160,200) <= 0
|   |   |   |   |   |   |   |   |   |   |   |   Trihalomethanes[30,40) <= 0
|   |   |   |   |   |   |   |   |   |   |   |   |   Organic_carbon[12,16) <= 0: Potable (3.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   Organic_carbon[12,16) > 0
|   |   |   |   |   |   |   |   |   |   |   |   |   |   Trihalomethanes[50,60) <= 0: Not Potable (2.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   |   Trihalomethanes[50,60) > 0: Potable (1.0)
|   |   |   |   |   |   |   |   |   |   |   |   Trihalomethanes[30,40) > 0: Not Potable (1.0)
|   |   |   |   |   |   |   |   |   |   |   Hardness[160,200) > 0: Not Potable (2.0)
|   |   |   |   |   |   |   |   |   |   Sulfate[264,308) > 0
|   |   |   |   |   |   |   |   |   |   |   Hardness[200,240) <= 0
|   |   |   |   |   |   |   |   |   |   |   |   Trihalomethanes[50,60) <= 0
|   |   |   |   |   |   |   |   |   |   |   |   |   Organic_carbon[16,20) <= 0
|   |   |   |   |   |   |   |   |   |   |   |   |   |   Conductivity[500,600) <= 0
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   Hardness[160,200) <= 0
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   Conductivity[300,400) <= 0: Not Potable (1.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   Conductivity[300,400) > 0: Potable (2.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   Hardness[160,200) > 0
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   Trihalomethanes[100,110) <= 0
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   Trihalomethanes[60,70) <= 0: Not Potable (2.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   Trihalomethanes[60,70) > 0
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   Chloramines[7,11) <= 0
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   Organic_carbon[8,12) <= 0
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   Conductivity[300,400) <= 0: Potable (4.0/1.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   Conductivity[300,400) > 0: Not Potable (1.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   Organic_carbon[8,12) > 0
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   Conductivity[300,400) <= 0: Not Potable (2.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   Conductivity[300,400) > 0: Potable (1.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   Chloramines[7,11) > 0
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   Organic_carbon[8,12) <= 0: Not Potable (6.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   Organic_carbon[8,12) > 0: Potable (1.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   Trihalomethanes[100,110) > 0: Potable (1.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   |   Conductivity[500,600) > 0: Not Potable (6.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   Organic_carbon[16,20) > 0
|   |   |   |   |   |   |   |   |   |   |   |   |   |   Chloramines[7,11) <= 0: Potable (3.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   |   Chloramines[7,11) > 0: Not Potable (3.0/1.0)
|   |   |   |   |   |   |   |   |   |   |   |   Trihalomethanes[50,60) > 0: Not Potable (11.0/1.0)
|   |   |   |   |   |   |   |   |   |   |   Hardness[200,240) > 0
|   |   |   |   |   |   |   |   |   |   |   |   Trihalomethanes[60,70) <= 0
|   |   |   |   |   |   |   |   |   |   |   |   |   Chloramines[7,11) <= 0: Not Potable (5.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   Chloramines[7,11) > 0
|   |   |   |   |   |   |   |   |   |   |   |   |   |   Organic_carbon[12,16) <= 0
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   Conductivity[300,400) <= 0: Not Potable (5.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   Conductivity[300,400) > 0
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   Organic_carbon[8,12) <= 0: Potable (2.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   Organic_carbon[8,12) > 0: Not Potable (1.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   |   Organic_carbon[12,16) > 0: Potable (2.0)
|   |   |   |   |   |   |   |   |   |   |   |   Trihalomethanes[60,70) > 0: Not Potable (13.0)
|   |   |   |   |   |   |   |   |   Hardness[240,280) > 0
|   |   |   |   |   |   |   |   |   |   Conductivity[500,600) <= 0: Not Potable (6.0)
|   |   |   |   |   |   |   |   |   |   Conductivity[500,600) > 0: Potable (1.0)
|   |   |   |   |   |   |   |   Trihalomethanes[80,90) > 0
|   |   |   |   |   |   |   |   |   Conductivity[500,600) <= 0
|   |   |   |   |   |   |   |   |   |   Solids <= 0.807853: Not Potable (19.0)
|   |   |   |   |   |   |   |   |   |   Solids > 0.807853: Potable (1.0)
|   |   |   |   |   |   |   |   |   Conductivity[500,600) > 0: Potable (2.0)
|   |   |   |   |   |   Trihalomethanes[70,80) > 0
|   |   |   |   |   |   |   Turbidity[3,5) <= 0: Not Potable (7.0)
|   |   |   |   |   |   |   Turbidity[3,5) > 0
|   |   |   |   |   |   |   |   Organic_carbon[16,20) <= 0
|   |   |   |   |   |   |   |   |   Hardness[240,280) <= 0
|   |   |   |   |   |   |   |   |   |   Sulfate[264,308) <= 0: Potable (3.0)
|   |   |   |   |   |   |   |   |   |   Sulfate[264,308) > 0
|   |   |   |   |   |   |   |   |   |   |   Conductivity[500,600) <= 0
|   |   |   |   |   |   |   |   |   |   |   |   Hardness[160,200) <= 0
|   |   |   |   |   |   |   |   |   |   |   |   |   Organic_carbon[8,12) <= 0
|   |   |   |   |   |   |   |   |   |   |   |   |   |   Solids <= 0.394234: Potable (1.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   |   Solids > 0.394234: Not Potable (6.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   Organic_carbon[8,12) > 0
|   |   |   |   |   |   |   |   |   |   |   |   |   |   Hardness[200,240) <= 0: Not Potable (1.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   |   Hardness[200,240) > 0
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   Solids <= 0.195778: Not Potable (1.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   Solids > 0.195778: Potable (3.0)
|   |   |   |   |   |   |   |   |   |   |   |   Hardness[160,200) > 0
|   |   |   |   |   |   |   |   |   |   |   |   |   Conductivity[300,400) <= 0
|   |   |   |   |   |   |   |   |   |   |   |   |   |   Organic_carbon[8,12) <= 0
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   Solids <= 0.33921: Not Potable (1.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   Solids > 0.33921: Potable (3.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   |   Organic_carbon[8,12) > 0: Not Potable (2.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   Conductivity[300,400) > 0: Potable (2.0)
|   |   |   |   |   |   |   |   |   |   |   Conductivity[500,600) > 0: Potable (4.0/1.0)
|   |   |   |   |   |   |   |   |   Hardness[240,280) > 0: Not Potable (3.0)
|   |   |   |   |   |   |   |   Organic_carbon[16,20) > 0
|   |   |   |   |   |   |   |   |   Conductivity[500,600) <= 0: Potable (6.0)
|   |   |   |   |   |   |   |   |   Conductivity[500,600) > 0: Not Potable (1.0)
|   |   |   |   |   Sulfate[352,396) > 0
|   |   |   |   |   |   Hardness[240,280) <= 0
|   |   |   |   |   |   |   Chloramines[7,11) <= 0
|   |   |   |   |   |   |   |   Trihalomethanes[70,80) <= 0
|   |   |   |   |   |   |   |   |   Turbidity[5,7) <= 0
|   |   |   |   |   |   |   |   |   |   Organic_carbon[12,16) <= 0
|   |   |   |   |   |   |   |   |   |   |   Conductivity[500,600) <= 0
|   |   |   |   |   |   |   |   |   |   |   |   Turbidity[3,5) <= 0: Not Potable (1.0)
|   |   |   |   |   |   |   |   |   |   |   |   Turbidity[3,5) > 0
|   |   |   |   |   |   |   |   |   |   |   |   |   Hardness[160,200) <= 0
|   |   |   |   |   |   |   |   |   |   |   |   |   |   Trihalomethanes[50,60) <= 0
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   Trihalomethanes[60,70) <= 0: Potable (1.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   Trihalomethanes[60,70) > 0
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   Solids <= 0.377252: Not Potable (2.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   Solids > 0.377252: Potable (3.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   |   Trihalomethanes[50,60) > 0: Not Potable (2.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   Hardness[160,200) > 0
|   |   |   |   |   |   |   |   |   |   |   |   |   |   Trihalomethanes[60,70) <= 0: Potable (4.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   |   Trihalomethanes[60,70) > 0
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   Solids <= 0.421001: Not Potable (2.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   Solids > 0.421001: Potable (5.0)
|   |   |   |   |   |   |   |   |   |   |   Conductivity[500,600) > 0
|   |   |   |   |   |   |   |   |   |   |   |   Organic_carbon[16,20) <= 0: Not Potable (4.0)
|   |   |   |   |   |   |   |   |   |   |   |   Organic_carbon[16,20) > 0: Potable (2.0)
|   |   |   |   |   |   |   |   |   |   Organic_carbon[12,16) > 0
|   |   |   |   |   |   |   |   |   |   |   Trihalomethanes[80,90) <= 0
|   |   |   |   |   |   |   |   |   |   |   |   Turbidity[3,5) <= 0: Not Potable (1.0)
|   |   |   |   |   |   |   |   |   |   |   |   Turbidity[3,5) > 0: Potable (17.0/3.0)
|   |   |   |   |   |   |   |   |   |   |   Trihalomethanes[80,90) > 0: Not Potable (1.0)
|   |   |   |   |   |   |   |   |   Turbidity[5,7) > 0
|   |   |   |   |   |   |   |   |   |   Organic_carbon[12,16) <= 0: Potable (5.0)
|   |   |   |   |   |   |   |   |   |   Organic_carbon[12,16) > 0: Not Potable (1.0)
|   |   |   |   |   |   |   |   Trihalomethanes[70,80) > 0
|   |   |   |   |   |   |   |   |   Conductivity[600,700) <= 0
|   |   |   |   |   |   |   |   |   |   Conductivity[400,500) <= 0
|   |   |   |   |   |   |   |   |   |   |   Organic_carbon[16,20) <= 0
|   |   |   |   |   |   |   |   |   |   |   |   Conductivity[300,400) <= 0
|   |   |   |   |   |   |   |   |   |   |   |   |   Organic_carbon[8,12) <= 0: Potable (3.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   Organic_carbon[8,12) > 0: Not Potable (1.0)
|   |   |   |   |   |   |   |   |   |   |   |   Conductivity[300,400) > 0
|   |   |   |   |   |   |   |   |   |   |   |   |   Solids <= 0.673943: Not Potable (3.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   Solids > 0.673943: Potable (2.0)
|   |   |   |   |   |   |   |   |   |   |   Organic_carbon[16,20) > 0: Potable (1.0)
|   |   |   |   |   |   |   |   |   |   Conductivity[400,500) > 0
|   |   |   |   |   |   |   |   |   |   |   Turbidity[3,5) <= 0: Not Potable (1.0)
|   |   |   |   |   |   |   |   |   |   |   Turbidity[3,5) > 0
|   |   |   |   |   |   |   |   |   |   |   |   Organic_carbon[8,12) <= 0
|   |   |   |   |   |   |   |   |   |   |   |   |   Solids <= 0.201591: Potable (1.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   Solids > 0.201591: Not Potable (5.0)
|   |   |   |   |   |   |   |   |   |   |   |   Organic_carbon[8,12) > 0: Potable (1.0)
|   |   |   |   |   |   |   |   |   Conductivity[600,700) > 0: Potable (1.0)
|   |   |   |   |   |   |   Chloramines[7,11) > 0
|   |   |   |   |   |   |   |   Conductivity[300,400) <= 0
|   |   |   |   |   |   |   |   |   Conductivity[500,600) <= 0
|   |   |   |   |   |   |   |   |   |   Organic_carbon[12,16) <= 0
|   |   |   |   |   |   |   |   |   |   |   Conductivity[400,500) <= 0: Potable (4.0)
|   |   |   |   |   |   |   |   |   |   |   Conductivity[400,500) > 0
|   |   |   |   |   |   |   |   |   |   |   |   Hardness[160,200) <= 0
|   |   |   |   |   |   |   |   |   |   |   |   |   Organic_carbon[8,12) <= 0
|   |   |   |   |   |   |   |   |   |   |   |   |   |   Trihalomethanes[60,70) <= 0: Potable (4.0/1.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   |   Trihalomethanes[60,70) > 0: Not Potable (1.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   Organic_carbon[8,12) > 0
|   |   |   |   |   |   |   |   |   |   |   |   |   |   Solids <= 0.482566: Potable (6.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   |   Solids > 0.482566: Not Potable (1.0)
|   |   |   |   |   |   |   |   |   |   |   |   Hardness[160,200) > 0
|   |   |   |   |   |   |   |   |   |   |   |   |   Trihalomethanes[50,60) <= 0
|   |   |   |   |   |   |   |   |   |   |   |   |   |   Trihalomethanes[90,100) <= 0
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   Solids <= 0.561575: Potable (8.0/2.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   Solids > 0.561575: Not Potable (2.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   |   Trihalomethanes[90,100) > 0: Not Potable (1.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   Trihalomethanes[50,60) > 0: Not Potable (2.0)
|   |   |   |   |   |   |   |   |   |   Organic_carbon[12,16) > 0
|   |   |   |   |   |   |   |   |   |   |   Trihalomethanes[80,90) <= 0
|   |   |   |   |   |   |   |   |   |   |   |   Turbidity[3,5) <= 0: Not Potable (1.0)
|   |   |   |   |   |   |   |   |   |   |   |   Turbidity[3,5) > 0
|   |   |   |   |   |   |   |   |   |   |   |   |   Hardness[160,200) <= 0
|   |   |   |   |   |   |   |   |   |   |   |   |   |   Hardness[200,240) <= 0: Not Potable (6.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   |   Hardness[200,240) > 0: Potable (6.0/2.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   Hardness[160,200) > 0
|   |   |   |   |   |   |   |   |   |   |   |   |   |   Trihalomethanes[60,70) <= 0: Potable (3.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   |   Trihalomethanes[60,70) > 0: Not Potable (1.0)
|   |   |   |   |   |   |   |   |   |   |   Trihalomethanes[80,90) > 0: Not Potable (1.0)
|   |   |   |   |   |   |   |   |   Conductivity[500,600) > 0
|   |   |   |   |   |   |   |   |   |   Organic_carbon[16,20) <= 0
|   |   |   |   |   |   |   |   |   |   |   Organic_carbon[12,16) <= 0: Not Potable (9.0/1.0)
|   |   |   |   |   |   |   |   |   |   |   Organic_carbon[12,16) > 0
|   |   |   |   |   |   |   |   |   |   |   |   Trihalomethanes[70,80) <= 0
|   |   |   |   |   |   |   |   |   |   |   |   |   Turbidity[3,5) <= 0
|   |   |   |   |   |   |   |   |   |   |   |   |   |   Turbidity[5,7) <= 0: Not Potable (2.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   |   Turbidity[5,7) > 0
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   Solids <= 0.40018: Not Potable (1.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   Solids > 0.40018: Potable (3.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   Turbidity[3,5) > 0: Potable (4.0)
|   |   |   |   |   |   |   |   |   |   |   |   Trihalomethanes[70,80) > 0: Not Potable (1.0)
|   |   |   |   |   |   |   |   |   |   Organic_carbon[16,20) > 0: Potable (1.0)
|   |   |   |   |   |   |   |   Conductivity[300,400) > 0
|   |   |   |   |   |   |   |   |   Trihalomethanes[100,110) <= 0
|   |   |   |   |   |   |   |   |   |   Organic_carbon[8,12) <= 0
|   |   |   |   |   |   |   |   |   |   |   Turbidity[5,7) <= 0
|   |   |   |   |   |   |   |   |   |   |   |   Trihalomethanes[30,40) <= 0
|   |   |   |   |   |   |   |   |   |   |   |   |   Hardness[200,240) <= 0: Not Potable (14.0/1.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   Hardness[200,240) > 0
|   |   |   |   |   |   |   |   |   |   |   |   |   |   Trihalomethanes[90,100) <= 0: Potable (4.0/1.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   |   Trihalomethanes[90,100) > 0: Not Potable (1.0)
|   |   |   |   |   |   |   |   |   |   |   |   Trihalomethanes[30,40) > 0: Potable (1.0)
|   |   |   |   |   |   |   |   |   |   |   Turbidity[5,7) > 0: Not Potable (1.0)
|   |   |   |   |   |   |   |   |   |   Organic_carbon[8,12) > 0: Not Potable (4.0)
|   |   |   |   |   |   |   |   |   Trihalomethanes[100,110) > 0: Potable (1.0)
|   |   |   |   |   |   Hardness[240,280) > 0
|   |   |   |   |   |   |   Conductivity[500,600) <= 0: Potable (8.0/1.0)
|   |   |   |   |   |   |   Conductivity[500,600) > 0: Not Potable (1.0)
|   |   |   |   ph[7,11) > 0
|   |   |   |   |   Sulfate[352,396) <= 0
|   |   |   |   |   |   Sulfate[264,308) <= 0
|   |   |   |   |   |   |   Solids <= 0.233755: Not Potable (2.0)
|   |   |   |   |   |   |   Solids > 0.233755
|   |   |   |   |   |   |   |   Hardness[240,280) <= 0: Potable (18.0/1.0)
|   |   |   |   |   |   |   |   Hardness[240,280) > 0: Not Potable (1.0)
|   |   |   |   |   |   Sulfate[264,308) > 0
|   |   |   |   |   |   |   Hardness[200,240) <= 0
|   |   |   |   |   |   |   |   Chloramines[7,11) <= 0
|   |   |   |   |   |   |   |   |   Trihalomethanes[50,60) <= 0
|   |   |   |   |   |   |   |   |   |   Solids <= 0.509695: Not Potable (20.0/4.0)
|   |   |   |   |   |   |   |   |   |   Solids > 0.509695
|   |   |   |   |   |   |   |   |   |   |   Hardness[240,280) <= 0: Potable (17.0/2.0)
|   |   |   |   |   |   |   |   |   |   |   Hardness[240,280) > 0
|   |   |   |   |   |   |   |   |   |   |   |   Organic_carbon[12,16) <= 0: Potable (2.0)
|   |   |   |   |   |   |   |   |   |   |   |   Organic_carbon[12,16) > 0: Not Potable (3.0)
|   |   |   |   |   |   |   |   |   Trihalomethanes[50,60) > 0: Potable (4.0)
|   |   |   |   |   |   |   |   Chloramines[7,11) > 0
|   |   |   |   |   |   |   |   |   Organic_carbon[12,16) <= 0
|   |   |   |   |   |   |   |   |   |   Conductivity[300,400) <= 0
|   |   |   |   |   |   |   |   |   |   |   Trihalomethanes[90,100) <= 0
|   |   |   |   |   |   |   |   |   |   |   |   Solids <= 0.741689
|   |   |   |   |   |   |   |   |   |   |   |   |   Conductivity[500,600) <= 0
|   |   |   |   |   |   |   |   |   |   |   |   |   |   Trihalomethanes[60,70) <= 0
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   Turbidity[5,7) <= 0
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   Organic_carbon[8,12) <= 0: Potable (2.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   Organic_carbon[8,12) > 0
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   Hardness[160,200) <= 0: Potable (1.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   Hardness[160,200) > 0
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   Solids <= 0.445778: Potable (1.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   Solids > 0.445778: Not Potable (2.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   Turbidity[5,7) > 0: Not Potable (1.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   |   Trihalomethanes[60,70) > 0: Not Potable (2.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   Conductivity[500,600) > 0: Not Potable (3.0)
|   |   |   |   |   |   |   |   |   |   |   |   Solids > 0.741689: Potable (6.0)
|   |   |   |   |   |   |   |   |   |   |   Trihalomethanes[90,100) > 0: Potable (1.0)
|   |   |   |   |   |   |   |   |   |   Conductivity[300,400) > 0: Potable (4.0)
|   |   |   |   |   |   |   |   |   Organic_carbon[12,16) > 0: Potable (21.0/2.0)
|   |   |   |   |   |   |   Hardness[200,240) > 0
|   |   |   |   |   |   |   |   Trihalomethanes[30,40) <= 0
|   |   |   |   |   |   |   |   |   Trihalomethanes[80,90) <= 0
|   |   |   |   |   |   |   |   |   |   Organic_carbon[12,16) <= 0
|   |   |   |   |   |   |   |   |   |   |   Trihalomethanes[70,80) <= 0
|   |   |   |   |   |   |   |   |   |   |   |   Conductivity[300,400) <= 0
|   |   |   |   |   |   |   |   |   |   |   |   |   Trihalomethanes[60,70) <= 0
|   |   |   |   |   |   |   |   |   |   |   |   |   |   Organic_carbon[8,12) <= 0: Not Potable (6.0/1.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   |   Organic_carbon[8,12) > 0: Potable (5.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   Trihalomethanes[60,70) > 0: Not Potable (7.0)
|   |   |   |   |   |   |   |   |   |   |   |   Conductivity[300,400) > 0
|   |   |   |   |   |   |   |   |   |   |   |   |   Trihalomethanes[50,60) <= 0: Potable (8.0/1.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   Trihalomethanes[50,60) > 0: Not Potable (2.0)
|   |   |   |   |   |   |   |   |   |   |   Trihalomethanes[70,80) > 0
|   |   |   |   |   |   |   |   |   |   |   |   Solids <= 0.819072: Not Potable (14.0)
|   |   |   |   |   |   |   |   |   |   |   |   Solids > 0.819072: Potable (1.0)
|   |   |   |   |   |   |   |   |   |   Organic_carbon[12,16) > 0
|   |   |   |   |   |   |   |   |   |   |   Trihalomethanes[90,100) <= 0
|   |   |   |   |   |   |   |   |   |   |   |   Trihalomethanes[60,70) <= 0
|   |   |   |   |   |   |   |   |   |   |   |   |   Chloramines[7,11) <= 0
|   |   |   |   |   |   |   |   |   |   |   |   |   |   Solids <= 0.520975: Not Potable (4.0/1.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   |   Solids > 0.520975: Potable (4.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   Chloramines[7,11) > 0
|   |   |   |   |   |   |   |   |   |   |   |   |   |   Solids <= 0.807853: Potable (6.0/1.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   |   Solids > 0.807853: Not Potable (1.0)
|   |   |   |   |   |   |   |   |   |   |   |   Trihalomethanes[60,70) > 0
|   |   |   |   |   |   |   |   |   |   |   |   |   Conductivity[300,400) <= 0
|   |   |   |   |   |   |   |   |   |   |   |   |   |   Turbidity[3,5) <= 0: Not Potable (3.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   |   Turbidity[3,5) > 0
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   Solids <= 0.315273: Not Potable (2.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   Solids > 0.315273: Potable (3.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   Conductivity[300,400) > 0: Potable (3.0)
|   |   |   |   |   |   |   |   |   |   |   Trihalomethanes[90,100) > 0: Not Potable (2.0)
|   |   |   |   |   |   |   |   |   Trihalomethanes[80,90) > 0
|   |   |   |   |   |   |   |   |   |   Solids <= 0.388146: Not Potable (2.0)
|   |   |   |   |   |   |   |   |   |   Solids > 0.388146: Potable (5.0)
|   |   |   |   |   |   |   |   Trihalomethanes[30,40) > 0
|   |   |   |   |   |   |   |   |   Organic_carbon[12,16) <= 0: Potable (4.0)
|   |   |   |   |   |   |   |   |   Organic_carbon[12,16) > 0: Not Potable (1.0)
|   |   |   |   |   Sulfate[352,396) > 0
|   |   |   |   |   |   Hardness[200,240) <= 0
|   |   |   |   |   |   |   Trihalomethanes[30,40) <= 0
|   |   |   |   |   |   |   |   Turbidity[3,5) <= 0: Not Potable (22.0/2.0)
|   |   |   |   |   |   |   |   Turbidity[3,5) > 0
|   |   |   |   |   |   |   |   |   Trihalomethanes[70,80) <= 0
|   |   |   |   |   |   |   |   |   |   Trihalomethanes[80,90) <= 0
|   |   |   |   |   |   |   |   |   |   |   Hardness[160,200) <= 0
|   |   |   |   |   |   |   |   |   |   |   |   Chloramines[7,11) <= 0
|   |   |   |   |   |   |   |   |   |   |   |   |   Conductivity[400,500) <= 0: Potable (5.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   Conductivity[400,500) > 0: Not Potable (4.0/1.0)
|   |   |   |   |   |   |   |   |   |   |   |   Chloramines[7,11) > 0
|   |   |   |   |   |   |   |   |   |   |   |   |   Organic_carbon[16,20) <= 0
|   |   |   |   |   |   |   |   |   |   |   |   |   |   Hardness[240,280) <= 0
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   Conductivity[300,400) <= 0
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   Solids <= 0.541894: Potable (3.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   Solids > 0.541894: Not Potable (1.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   Conductivity[300,400) > 0: Not Potable (2.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   |   Hardness[240,280) > 0: Not Potable (5.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   Organic_carbon[16,20) > 0: Potable (1.0)
|   |   |   |   |   |   |   |   |   |   |   Hardness[160,200) > 0
|   |   |   |   |   |   |   |   |   |   |   |   Chloramines[7,11) <= 0
|   |   |   |   |   |   |   |   |   |   |   |   |   Conductivity[400,500) <= 0
|   |   |   |   |   |   |   |   |   |   |   |   |   |   Trihalomethanes[90,100) <= 0
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   Organic_carbon[8,12) <= 0
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   Conductivity[500,600) <= 0: Not Potable (3.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   Conductivity[500,600) > 0
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   Organic_carbon[12,16) <= 0: Potable (1.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   Organic_carbon[12,16) > 0
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   Solids <= 0.455149: Not Potable (2.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   Solids > 0.455149: Potable (2.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   Organic_carbon[8,12) > 0
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   Solids <= 0.272424: Not Potable (1.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   Solids > 0.272424: Potable (2.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   |   Trihalomethanes[90,100) > 0: Not Potable (3.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   Conductivity[400,500) > 0: Not Potable (5.0)
|   |   |   |   |   |   |   |   |   |   |   |   Chloramines[7,11) > 0
|   |   |   |   |   |   |   |   |   |   |   |   |   Trihalomethanes[90,100) <= 0
|   |   |   |   |   |   |   |   |   |   |   |   |   |   Conductivity[500,600) <= 0
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   Trihalomethanes[60,70) <= 0: Not Potable (7.0/2.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   Trihalomethanes[60,70) > 0
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   Organic_carbon[8,12) <= 0
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   Conductivity[300,400) <= 0
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   Organic_carbon[12,16) <= 0
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   Solids <= 0.431273: Not Potable (1.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   Solids > 0.431273: Potable (1.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   Organic_carbon[12,16) > 0
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   Solids <= 0.43104: Potable (2.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   Solids > 0.43104: Not Potable (1.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   Conductivity[300,400) > 0: Not Potable (2.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   Organic_carbon[8,12) > 0: Potable (1.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   |   Conductivity[500,600) > 0: Not Potable (2.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   Trihalomethanes[90,100) > 0: Potable (2.0)
|   |   |   |   |   |   |   |   |   |   Trihalomethanes[80,90) > 0
|   |   |   |   |   |   |   |   |   |   |   Hardness[160,200) <= 0: Not Potable (5.0)
|   |   |   |   |   |   |   |   |   |   |   Hardness[160,200) > 0
|   |   |   |   |   |   |   |   |   |   |   |   Conductivity[500,600) <= 0
|   |   |   |   |   |   |   |   |   |   |   |   |   Solids <= 0.630566: Not Potable (10.0/1.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   Solids > 0.630566: Potable (2.0)
|   |   |   |   |   |   |   |   |   |   |   |   Conductivity[500,600) > 0: Potable (1.0)
|   |   |   |   |   |   |   |   |   Trihalomethanes[70,80) > 0: Not Potable (15.0/3.0)
|   |   |   |   |   |   |   Trihalomethanes[30,40) > 0: Not Potable (7.0)
|   |   |   |   |   |   Hardness[200,240) > 0
|   |   |   |   |   |   |   Chloramines[7,11) <= 0
|   |   |   |   |   |   |   |   Trihalomethanes[70,80) <= 0
|   |   |   |   |   |   |   |   |   Organic_carbon[8,12) <= 0: Not Potable (22.0/5.0)
|   |   |   |   |   |   |   |   |   Organic_carbon[8,12) > 0
|   |   |   |   |   |   |   |   |   |   Solids <= 0.586899: Potable (6.0)
|   |   |   |   |   |   |   |   |   |   Solids > 0.586899: Not Potable (2.0)
|   |   |   |   |   |   |   |   Trihalomethanes[70,80) > 0: Not Potable (5.0)
|   |   |   |   |   |   |   Chloramines[7,11) > 0
|   |   |   |   |   |   |   |   Turbidity[3,5) <= 0
|   |   |   |   |   |   |   |   |   Conductivity[500,600) <= 0: Potable (8.0)
|   |   |   |   |   |   |   |   |   Conductivity[500,600) > 0: Not Potable (1.0)
|   |   |   |   |   |   |   |   Turbidity[3,5) > 0
|   |   |   |   |   |   |   |   |   Conductivity[500,600) <= 0
|   |   |   |   |   |   |   |   |   |   Trihalomethanes[30,40) <= 0
|   |   |   |   |   |   |   |   |   |   |   Organic_carbon[8,12) <= 0
|   |   |   |   |   |   |   |   |   |   |   |   Conductivity[400,500) <= 0
|   |   |   |   |   |   |   |   |   |   |   |   |   Trihalomethanes[100,110) <= 0
|   |   |   |   |   |   |   |   |   |   |   |   |   |   Trihalomethanes[80,90) <= 0
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   Conductivity[300,400) <= 0: Potable (1.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   Conductivity[300,400) > 0
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   Trihalomethanes[60,70) <= 0
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   Organic_carbon[12,16) <= 0
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   Organic_carbon[16,20) <= 0: Not Potable (1.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   Organic_carbon[16,20) > 0
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   Solids <= 0.818584: Potable (3.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   Solids > 0.818584: Not Potable (1.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   Organic_carbon[12,16) > 0: Potable (2.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   Trihalomethanes[60,70) > 0
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   Solids <= 0.377252: Potable (1.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   Solids > 0.377252: Not Potable (2.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   |   Trihalomethanes[80,90) > 0: Not Potable (1.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   Trihalomethanes[100,110) > 0: Not Potable (2.0)
|   |   |   |   |   |   |   |   |   |   |   |   Conductivity[400,500) > 0
|   |   |   |   |   |   |   |   |   |   |   |   |   Trihalomethanes[80,90) <= 0
|   |   |   |   |   |   |   |   |   |   |   |   |   |   Trihalomethanes[70,80) <= 0
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   Trihalomethanes[50,60) <= 0
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   Solids <= 0.535701: Not Potable (2.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   Solids > 0.535701: Potable (2.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   Trihalomethanes[50,60) > 0: Not Potable (2.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   |   Trihalomethanes[70,80) > 0: Not Potable (3.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   Trihalomethanes[80,90) > 0: Potable (1.0)
|   |   |   |   |   |   |   |   |   |   |   Organic_carbon[8,12) > 0
|   |   |   |   |   |   |   |   |   |   |   |   Trihalomethanes[90,100) <= 0: Not Potable (4.0)
|   |   |   |   |   |   |   |   |   |   |   |   Trihalomethanes[90,100) > 0: Potable (1.0)
|   |   |   |   |   |   |   |   |   |   Trihalomethanes[30,40) > 0
|   |   |   |   |   |   |   |   |   |   |   Organic_carbon[12,16) <= 0: Not Potable (1.0)
|   |   |   |   |   |   |   |   |   |   |   Organic_carbon[12,16) > 0: Potable (2.0)
|   |   |   |   |   |   |   |   |   Conductivity[500,600) > 0
|   |   |   |   |   |   |   |   |   |   Organic_carbon[8,12) <= 0: Potable (6.0)
|   |   |   |   |   |   |   |   |   |   Organic_carbon[8,12) > 0: Not Potable (1.0)
|   |   |   Organic_carbon[20,24) > 0
|   |   |   |   Hardness[240,280) <= 0
|   |   |   |   |   Turbidity[5,7) <= 0
|   |   |   |   |   |   Sulfate[264,308) <= 0
|   |   |   |   |   |   |   Chloramines[7,11) <= 0: Not Potable (8.0/1.0)
|   |   |   |   |   |   |   Chloramines[7,11) > 0
|   |   |   |   |   |   |   |   Turbidity[3,5) <= 0: Potable (2.0)
|   |   |   |   |   |   |   |   Turbidity[3,5) > 0
|   |   |   |   |   |   |   |   |   Conductivity[400,500) <= 0
|   |   |   |   |   |   |   |   |   |   Trihalomethanes[100,110) <= 0: Not Potable (6.0/1.0)
|   |   |   |   |   |   |   |   |   |   Trihalomethanes[100,110) > 0: Potable (1.0)
|   |   |   |   |   |   |   |   |   Conductivity[400,500) > 0: Potable (1.0)
|   |   |   |   |   |   Sulfate[264,308) > 0
|   |   |   |   |   |   |   Hardness[200,240) <= 0: Potable (3.0)
|   |   |   |   |   |   |   Hardness[200,240) > 0
|   |   |   |   |   |   |   |   Trihalomethanes[70,80) <= 0: Potable (1.0)
|   |   |   |   |   |   |   |   Trihalomethanes[70,80) > 0: Not Potable (2.0)
|   |   |   |   |   Turbidity[5,7) > 0: Potable (3.0)
|   |   |   |   Hardness[240,280) > 0: Potable (3.0)
|   |   Trihalomethanes[40,50) > 0
|   |   |   Organic_carbon[16,20) <= 0
|   |   |   |   ph[7,11) <= 0
|   |   |   |   |   Turbidity[5,7) <= 0
|   |   |   |   |   |   Hardness[240,280) <= 0
|   |   |   |   |   |   |   Conductivity[400,500) <= 0
|   |   |   |   |   |   |   |   Turbidity[3,5) <= 0: Potable (1.0)
|   |   |   |   |   |   |   |   Turbidity[3,5) > 0
|   |   |   |   |   |   |   |   |   Organic_carbon[20,24) <= 0
|   |   |   |   |   |   |   |   |   |   Organic_carbon[12,16) <= 0: Potable (5.0/1.0)
|   |   |   |   |   |   |   |   |   |   Organic_carbon[12,16) > 0
|   |   |   |   |   |   |   |   |   |   |   Chloramines[7,11) <= 0
|   |   |   |   |   |   |   |   |   |   |   |   Conductivity[300,400) <= 0
|   |   |   |   |   |   |   |   |   |   |   |   |   Solids <= 0.62018: Not Potable (2.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   Solids > 0.62018: Potable (2.0)
|   |   |   |   |   |   |   |   |   |   |   |   Conductivity[300,400) > 0
|   |   |   |   |   |   |   |   |   |   |   |   |   Solids <= 0.283695: Potable (1.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   Solids > 0.283695: Not Potable (4.0)
|   |   |   |   |   |   |   |   |   |   |   Chloramines[7,11) > 0: Not Potable (6.0/1.0)
|   |   |   |   |   |   |   |   |   Organic_carbon[20,24) > 0: Not Potable (1.0)
|   |   |   |   |   |   |   Conductivity[400,500) > 0
|   |   |   |   |   |   |   |   Solids <= 0.394436: Potable (1.0)
|   |   |   |   |   |   |   |   Solids > 0.394436: Not Potable (5.0)
|   |   |   |   |   |   Hardness[240,280) > 0: Not Potable (2.0)
|   |   |   |   |   Turbidity[5,7) > 0: Not Potable (3.0)
|   |   |   |   ph[7,11) > 0
|   |   |   |   |   Hardness[240,280) <= 0
|   |   |   |   |   |   Organic_carbon[8,12) <= 0
|   |   |   |   |   |   |   Organic_carbon[12,16) <= 0: Potable (2.0)
|   |   |   |   |   |   |   Organic_carbon[12,16) > 0
|   |   |   |   |   |   |   |   Hardness[200,240) <= 0: Potable (7.0/2.0)
|   |   |   |   |   |   |   |   Hardness[200,240) > 0
|   |   |   |   |   |   |   |   |   Chloramines[7,11) <= 0
|   |   |   |   |   |   |   |   |   |   Turbidity[3,5) <= 0
|   |   |   |   |   |   |   |   |   |   |   Turbidity[5,7) <= 0: Not Potable (2.0)
|   |   |   |   |   |   |   |   |   |   |   Turbidity[5,7) > 0
|   |   |   |   |   |   |   |   |   |   |   |   Conductivity[400,500) <= 0: Potable (2.0)
|   |   |   |   |   |   |   |   |   |   |   |   Conductivity[400,500) > 0: Not Potable (1.0)
|   |   |   |   |   |   |   |   |   |   Turbidity[3,5) > 0: Potable (2.0)
|   |   |   |   |   |   |   |   |   Chloramines[7,11) > 0: Not Potable (2.0)
|   |   |   |   |   |   Organic_carbon[8,12) > 0
|   |   |   |   |   |   |   Sulfate[264,308) <= 0: Not Potable (6.0)
|   |   |   |   |   |   |   Sulfate[264,308) > 0: Potable (1.0)
|   |   |   |   |   Hardness[240,280) > 0: Potable (2.0)
|   |   |   Organic_carbon[16,20) > 0
|   |   |   |   Sulfate[264,308) <= 0
|   |   |   |   |   Sulfate[352,396) <= 0: Potable (1.0)
|   |   |   |   |   Sulfate[352,396) > 0
|   |   |   |   |   |   Hardness[160,200) <= 0
|   |   |   |   |   |   |   Hardness[200,240) <= 0: Potable (2.0)
|   |   |   |   |   |   |   Hardness[200,240) > 0
|   |   |   |   |   |   |   |   Solids <= 0.544185: Not Potable (3.0)
|   |   |   |   |   |   |   |   Solids > 0.544185: Potable (1.0)
|   |   |   |   |   |   Hardness[160,200) > 0: Not Potable (5.0)
|   |   |   |   Sulfate[264,308) > 0: Not Potable (8.0)
|   Sulfate[308,352) > 0
|   |   Hardness[240,280) <= 0
|   |   |   Trihalomethanes[90,100) <= 0
|   |   |   |   Hardness[160,200) <= 0
|   |   |   |   |   Hardness[200,240) <= 0
|   |   |   |   |   |   ph[7,11) <= 0
|   |   |   |   |   |   |   Trihalomethanes[60,70) <= 0
|   |   |   |   |   |   |   |   Conductivity[300,400) <= 0
|   |   |   |   |   |   |   |   |   Organic_carbon[8,12) <= 0
|   |   |   |   |   |   |   |   |   |   Trihalomethanes[40,50) <= 0: Potable (11.0/1.0)
|   |   |   |   |   |   |   |   |   |   Trihalomethanes[40,50) > 0
|   |   |   |   |   |   |   |   |   |   |   Conductivity[400,500) <= 0: Not Potable (4.0)
|   |   |   |   |   |   |   |   |   |   |   Conductivity[400,500) > 0: Potable (1.0)
|   |   |   |   |   |   |   |   |   Organic_carbon[8,12) > 0
|   |   |   |   |   |   |   |   |   |   Trihalomethanes[80,90) <= 0: Not Potable (4.0)
|   |   |   |   |   |   |   |   |   |   Trihalomethanes[80,90) > 0: Potable (1.0)
|   |   |   |   |   |   |   |   Conductivity[300,400) > 0
|   |   |   |   |   |   |   |   |   Trihalomethanes[40,50) <= 0: Not Potable (9.0/1.0)
|   |   |   |   |   |   |   |   |   Trihalomethanes[40,50) > 0: Potable (1.0)
|   |   |   |   |   |   |   Trihalomethanes[60,70) > 0
|   |   |   |   |   |   |   |   Chloramines[7,11) <= 0
|   |   |   |   |   |   |   |   |   Conductivity[300,400) <= 0
|   |   |   |   |   |   |   |   |   |   Solids <= 0.310076: Potable (1.0)
|   |   |   |   |   |   |   |   |   |   Solids > 0.310076: Not Potable (3.0)
|   |   |   |   |   |   |   |   |   Conductivity[300,400) > 0: Potable (1.0)
|   |   |   |   |   |   |   |   Chloramines[7,11) > 0: Not Potable (6.0)
|   |   |   |   |   |   ph[7,11) > 0
|   |   |   |   |   |   |   Trihalomethanes[40,50) <= 0
|   |   |   |   |   |   |   |   Turbidity[5,7) <= 0
|   |   |   |   |   |   |   |   |   Trihalomethanes[80,90) <= 0: Potable (15.0/2.0)
|   |   |   |   |   |   |   |   |   Trihalomethanes[80,90) > 0: Not Potable (3.0/1.0)
|   |   |   |   |   |   |   |   Turbidity[5,7) > 0: Not Potable (1.0)
|   |   |   |   |   |   |   Trihalomethanes[40,50) > 0: Not Potable (2.0)
|   |   |   |   |   Hardness[200,240) > 0
|   |   |   |   |   |   Chloramines[7,11) <= 0
|   |   |   |   |   |   |   Turbidity[3,5) <= 0
|   |   |   |   |   |   |   |   Organic_carbon[16,20) <= 0: Not Potable (16.0)
|   |   |   |   |   |   |   |   Organic_carbon[16,20) > 0
|   |   |   |   |   |   |   |   |   ph[7,11) <= 0: Potable (3.0)
|   |   |   |   |   |   |   |   |   ph[7,11) > 0: Not Potable (2.0)
|   |   |   |   |   |   |   Turbidity[3,5) > 0
|   |   |   |   |   |   |   |   Trihalomethanes[30,40) <= 0
|   |   |   |   |   |   |   |   |   ph[7,11) <= 0
|   |   |   |   |   |   |   |   |   |   Trihalomethanes[50,60) <= 0
|   |   |   |   |   |   |   |   |   |   |   Trihalomethanes[70,80) <= 0
|   |   |   |   |   |   |   |   |   |   |   |   Conductivity[500,600) <= 0
|   |   |   |   |   |   |   |   |   |   |   |   |   Conductivity[600,700) <= 0
|   |   |   |   |   |   |   |   |   |   |   |   |   |   Trihalomethanes[100,110) <= 0
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   Conductivity[400,500) <= 0
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   Trihalomethanes[80,90) <= 0: Potable (6.0/2.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   Trihalomethanes[80,90) > 0: Not Potable (2.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   Conductivity[400,500) > 0
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   Trihalomethanes[80,90) <= 0: Not Potable (8.0/1.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   Trihalomethanes[80,90) > 0: Potable (1.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   |   Trihalomethanes[100,110) > 0: Potable (1.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   Conductivity[600,700) > 0: Potable (1.0)
|   |   |   |   |   |   |   |   |   |   |   |   Conductivity[500,600) > 0: Potable (4.0)
|   |   |   |   |   |   |   |   |   |   |   Trihalomethanes[70,80) > 0
|   |   |   |   |   |   |   |   |   |   |   |   Organic_carbon[8,12) <= 0: Not Potable (14.0/3.0)
|   |   |   |   |   |   |   |   |   |   |   |   Organic_carbon[8,12) > 0: Potable (1.0)
|   |   |   |   |   |   |   |   |   |   Trihalomethanes[50,60) > 0
|   |   |   |   |   |   |   |   |   |   |   Organic_carbon[12,16) <= 0: Not Potable (7.0)
|   |   |   |   |   |   |   |   |   |   |   Organic_carbon[12,16) > 0: Potable (1.0)
|   |   |   |   |   |   |   |   |   ph[7,11) > 0
|   |   |   |   |   |   |   |   |   |   Organic_carbon[16,20) <= 0
|   |   |   |   |   |   |   |   |   |   |   Trihalomethanes[50,60) <= 0
|   |   |   |   |   |   |   |   |   |   |   |   Conductivity[400,500) <= 0: Not Potable (23.0/1.0)
|   |   |   |   |   |   |   |   |   |   |   |   Conductivity[400,500) > 0
|   |   |   |   |   |   |   |   |   |   |   |   |   Organic_carbon[8,12) <= 0
|   |   |   |   |   |   |   |   |   |   |   |   |   |   Trihalomethanes[70,80) <= 0
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   Solids <= 0.565998: Not Potable (9.0/2.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   Solids > 0.565998: Potable (2.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   |   Trihalomethanes[70,80) > 0
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   Solids <= 0.380268: Potable (1.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   Solids > 0.380268: Not Potable (2.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   Organic_carbon[8,12) > 0: Not Potable (2.0)
|   |   |   |   |   |   |   |   |   |   |   Trihalomethanes[50,60) > 0
|   |   |   |   |   |   |   |   |   |   |   |   Organic_carbon[12,16) <= 0: Potable (3.0)
|   |   |   |   |   |   |   |   |   |   |   |   Organic_carbon[12,16) > 0: Not Potable (8.0/1.0)
|   |   |   |   |   |   |   |   |   |   Organic_carbon[16,20) > 0
|   |   |   |   |   |   |   |   |   |   |   Trihalomethanes[70,80) <= 0
|   |   |   |   |   |   |   |   |   |   |   |   Conductivity[300,400) <= 0
|   |   |   |   |   |   |   |   |   |   |   |   |   Trihalomethanes[40,50) <= 0
|   |   |   |   |   |   |   |   |   |   |   |   |   |   Solids <= 0.487788
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   Solids <= 0.322012: Not Potable (1.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   Solids > 0.322012: Potable (3.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   |   Solids > 0.487788: Not Potable (4.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   Trihalomethanes[40,50) > 0: Potable (1.0)
|   |   |   |   |   |   |   |   |   |   |   |   Conductivity[300,400) > 0: Not Potable (3.0)
|   |   |   |   |   |   |   |   |   |   |   Trihalomethanes[70,80) > 0
|   |   |   |   |   |   |   |   |   |   |   |   Conductivity[500,600) <= 0: Potable (8.0/3.0)
|   |   |   |   |   |   |   |   |   |   |   |   Conductivity[500,600) > 0: Not Potable (1.0)
|   |   |   |   |   |   |   |   Trihalomethanes[30,40) > 0
|   |   |   |   |   |   |   |   |   Organic_carbon[12,16) <= 0: Potable (2.0)
|   |   |   |   |   |   |   |   |   Organic_carbon[12,16) > 0
|   |   |   |   |   |   |   |   |   |   Solids <= 0.577692: Not Potable (5.0)
|   |   |   |   |   |   |   |   |   |   Solids > 0.577692: Potable (2.0)
|   |   |   |   |   |   Chloramines[7,11) > 0
|   |   |   |   |   |   |   Turbidity[5,7) <= 0
|   |   |   |   |   |   |   |   Conductivity[500,600) <= 0
|   |   |   |   |   |   |   |   |   ph[7,11) <= 0
|   |   |   |   |   |   |   |   |   |   Trihalomethanes[40,50) <= 0
|   |   |   |   |   |   |   |   |   |   |   Organic_carbon[8,12) <= 0
|   |   |   |   |   |   |   |   |   |   |   |   Trihalomethanes[30,40) <= 0
|   |   |   |   |   |   |   |   |   |   |   |   |   Trihalomethanes[50,60) <= 0
|   |   |   |   |   |   |   |   |   |   |   |   |   |   Trihalomethanes[80,90) <= 0
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   Turbidity[3,5) <= 0: Potable (2.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   Turbidity[3,5) > 0
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   Conductivity[400,500) <= 0
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   Trihalomethanes[60,70) <= 0: Potable (3.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   Trihalomethanes[60,70) > 0
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   Conductivity[300,400) <= 0: Potable (2.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   Conductivity[300,400) > 0: Not Potable (3.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   Conductivity[400,500) > 0: Not Potable (10.0/3.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   |   Trihalomethanes[80,90) > 0: Not Potable (8.0/2.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   Trihalomethanes[50,60) > 0: Not Potable (7.0/1.0)
|   |   |   |   |   |   |   |   |   |   |   |   Trihalomethanes[30,40) > 0: Not Potable (2.0)
|   |   |   |   |   |   |   |   |   |   |   Organic_carbon[8,12) > 0: Not Potable (9.0/1.0)
|   |   |   |   |   |   |   |   |   |   Trihalomethanes[40,50) > 0: Not Potable (5.0)
|   |   |   |   |   |   |   |   |   ph[7,11) > 0
|   |   |   |   |   |   |   |   |   |   Trihalomethanes[40,50) <= 0
|   |   |   |   |   |   |   |   |   |   |   Trihalomethanes[30,40) <= 0
|   |   |   |   |   |   |   |   |   |   |   |   Trihalomethanes[50,60) <= 0
|   |   |   |   |   |   |   |   |   |   |   |   |   Organic_carbon[20,24) <= 0
|   |   |   |   |   |   |   |   |   |   |   |   |   |   Organic_carbon[16,20) <= 0
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   Organic_carbon[12,16) <= 0: Not Potable (8.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   Organic_carbon[12,16) > 0
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   Trihalomethanes[70,80) <= 0
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   Solids <= 0.357857: Potable (6.0/1.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   Solids > 0.357857
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   Conductivity[400,500) <= 0
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   Conductivity[300,400) <= 0: Potable (1.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   Conductivity[300,400) > 0
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   Solids <= 0.652077: Not Potable (3.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   Solids > 0.652077: Potable (1.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   Conductivity[400,500) > 0: Not Potable (4.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   Trihalomethanes[70,80) > 0: Not Potable (10.0/2.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   |   Organic_carbon[16,20) > 0
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   Trihalomethanes[60,70) <= 0
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   Trihalomethanes[70,80) <= 0: Not Potable (4.0/1.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   Trihalomethanes[70,80) > 0: Potable (2.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   Trihalomethanes[60,70) > 0: Potable (2.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   Organic_carbon[20,24) > 0: Potable (2.0)
|   |   |   |   |   |   |   |   |   |   |   |   Trihalomethanes[50,60) > 0
|   |   |   |   |   |   |   |   |   |   |   |   |   Organic_carbon[16,20) <= 0
|   |   |   |   |   |   |   |   |   |   |   |   |   |   Organic_carbon[8,12) <= 0
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   Conductivity[400,500) <= 0: Not Potable (2.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   Conductivity[400,500) > 0
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   Solids <= 0.585777: Potable (2.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   Solids > 0.585777: Not Potable (1.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   |   Organic_carbon[8,12) > 0: Potable (6.0/1.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   Organic_carbon[16,20) > 0: Not Potable (3.0)
|   |   |   |   |   |   |   |   |   |   |   Trihalomethanes[30,40) > 0
|   |   |   |   |   |   |   |   |   |   |   |   Solids <= 0.570578: Not Potable (3.0)
|   |   |   |   |   |   |   |   |   |   |   |   Solids > 0.570578: Potable (1.0)
|   |   |   |   |   |   |   |   |   |   Trihalomethanes[40,50) > 0
|   |   |   |   |   |   |   |   |   |   |   Organic_carbon[8,12) <= 0
|   |   |   |   |   |   |   |   |   |   |   |   Conductivity[300,400) <= 0: Potable (3.0)
|   |   |   |   |   |   |   |   |   |   |   |   Conductivity[300,400) > 0
|   |   |   |   |   |   |   |   |   |   |   |   |   Organic_carbon[12,16) <= 0
|   |   |   |   |   |   |   |   |   |   |   |   |   |   Solids <= 0.378233: Not Potable (1.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   |   Solids > 0.378233: Potable (2.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   Organic_carbon[12,16) > 0: Not Potable (1.0)
|   |   |   |   |   |   |   |   |   |   |   Organic_carbon[8,12) > 0: Not Potable (1.0)
|   |   |   |   |   |   |   |   Conductivity[500,600) > 0: Not Potable (23.0/4.0)
|   |   |   |   |   |   |   Turbidity[5,7) > 0
|   |   |   |   |   |   |   |   Conductivity[400,500) <= 0
|   |   |   |   |   |   |   |   |   Organic_carbon[16,20) <= 0
|   |   |   |   |   |   |   |   |   |   Trihalomethanes[70,80) <= 0: Potable (8.0/1.0)
|   |   |   |   |   |   |   |   |   |   Trihalomethanes[70,80) > 0: Not Potable (3.0/1.0)
|   |   |   |   |   |   |   |   |   Organic_carbon[16,20) > 0: Not Potable (1.0)
|   |   |   |   |   |   |   |   Conductivity[400,500) > 0: Not Potable (4.0)
|   |   |   |   Hardness[160,200) > 0
|   |   |   |   |   Trihalomethanes[50,60) <= 0
|   |   |   |   |   |   Conductivity[500,600) <= 0
|   |   |   |   |   |   |   Turbidity[3,5) <= 0: Not Potable (43.0/7.0)
|   |   |   |   |   |   |   Turbidity[3,5) > 0
|   |   |   |   |   |   |   |   Trihalomethanes[40,50) <= 0
|   |   |   |   |   |   |   |   |   Trihalomethanes[80,90) <= 0
|   |   |   |   |   |   |   |   |   |   Organic_carbon[8,12) <= 0
|   |   |   |   |   |   |   |   |   |   |   Trihalomethanes[60,70) <= 0
|   |   |   |   |   |   |   |   |   |   |   |   Organic_carbon[16,20) <= 0
|   |   |   |   |   |   |   |   |   |   |   |   |   Chloramines[7,11) <= 0
|   |   |   |   |   |   |   |   |   |   |   |   |   |   Conductivity[400,500) <= 0: Not Potable (6.0/1.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   |   Conductivity[400,500) > 0
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   Solids <= 0.506183: Not Potable (5.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   Solids > 0.506183: Potable (5.0/1.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   Chloramines[7,11) > 0: Not Potable (17.0/2.0)
|   |   |   |   |   |   |   |   |   |   |   |   Organic_carbon[16,20) > 0
|   |   |   |   |   |   |   |   |   |   |   |   |   ph[7,11) <= 0: Not Potable (9.0/2.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   ph[7,11) > 0
|   |   |   |   |   |   |   |   |   |   |   |   |   |   Chloramines[7,11) <= 0: Not Potable (6.0/1.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   |   Chloramines[7,11) > 0: Potable (3.0)
|   |   |   |   |   |   |   |   |   |   |   Trihalomethanes[60,70) > 0
|   |   |   |   |   |   |   |   |   |   |   |   Organic_carbon[16,20) <= 0
|   |   |   |   |   |   |   |   |   |   |   |   |   Conductivity[400,500) <= 0
|   |   |   |   |   |   |   |   |   |   |   |   |   |   Conductivity[600,700) <= 0
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   ph[7,11) <= 0: Not Potable (10.0/3.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   ph[7,11) > 0: Potable (8.0/2.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   |   Conductivity[600,700) > 0: Potable (1.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   Conductivity[400,500) > 0
|   |   |   |   |   |   |   |   |   |   |   |   |   |   Solids <= 0.757621: Not Potable (13.0/3.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   |   Solids > 0.757621: Potable (2.0)
|   |   |   |   |   |   |   |   |   |   |   |   Organic_carbon[16,20) > 0
|   |   |   |   |   |   |   |   |   |   |   |   |   Solids <= 0.54981: Not Potable (15.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   Solids > 0.54981
|   |   |   |   |   |   |   |   |   |   |   |   |   |   ph[7,11) <= 0
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   Chloramines[7,11) <= 0
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   Solids <= 0.713875: Potable (2.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   Solids > 0.713875: Not Potable (1.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   Chloramines[7,11) > 0: Not Potable (1.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   |   ph[7,11) > 0: Potable (2.0)
|   |   |   |   |   |   |   |   |   |   Organic_carbon[8,12) > 0
|   |   |   |   |   |   |   |   |   |   |   ph[7,11) <= 0: Not Potable (11.0/1.0)
|   |   |   |   |   |   |   |   |   |   |   ph[7,11) > 0
|   |   |   |   |   |   |   |   |   |   |   |   Solids <= 0.575729: Not Potable (11.0)
|   |   |   |   |   |   |   |   |   |   |   |   Solids > 0.575729
|   |   |   |   |   |   |   |   |   |   |   |   |   Conductivity[300,400) <= 0
|   |   |   |   |   |   |   |   |   |   |   |   |   |   Solids <= 0.801307: Not Potable (2.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   |   Solids > 0.801307: Potable (1.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   Conductivity[300,400) > 0: Potable (2.0)
|   |   |   |   |   |   |   |   |   Trihalomethanes[80,90) > 0
|   |   |   |   |   |   |   |   |   |   Organic_carbon[8,12) <= 0
|   |   |   |   |   |   |   |   |   |   |   Organic_carbon[12,16) <= 0
|   |   |   |   |   |   |   |   |   |   |   |   Conductivity[400,500) <= 0
|   |   |   |   |   |   |   |   |   |   |   |   |   ph[7,11) <= 0: Not Potable (4.0/1.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   ph[7,11) > 0: Potable (4.0)
|   |   |   |   |   |   |   |   |   |   |   |   Conductivity[400,500) > 0
|   |   |   |   |   |   |   |   |   |   |   |   |   ph[7,11) <= 0
|   |   |   |   |   |   |   |   |   |   |   |   |   |   Solids <= 0.594774: Potable (2.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   |   Solids > 0.594774: Not Potable (1.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   ph[7,11) > 0: Not Potable (3.0)
|   |   |   |   |   |   |   |   |   |   |   Organic_carbon[12,16) > 0
|   |   |   |   |   |   |   |   |   |   |   |   Chloramines[7,11) <= 0
|   |   |   |   |   |   |   |   |   |   |   |   |   Solids <= 0.501397: Not Potable (4.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   Solids > 0.501397: Potable (2.0)
|   |   |   |   |   |   |   |   |   |   |   |   Chloramines[7,11) > 0: Not Potable (7.0)
|   |   |   |   |   |   |   |   |   |   Organic_carbon[8,12) > 0: Potable (2.0)
|   |   |   |   |   |   |   |   Trihalomethanes[40,50) > 0
|   |   |   |   |   |   |   |   |   Organic_carbon[8,12) <= 0
|   |   |   |   |   |   |   |   |   |   Chloramines[7,11) <= 0
|   |   |   |   |   |   |   |   |   |   |   Solids <= 0.764996: Not Potable (10.0/1.0)
|   |   |   |   |   |   |   |   |   |   |   Solids > 0.764996
|   |   |   |   |   |   |   |   |   |   |   |   Solids <= 0.883745: Potable (2.0)
|   |   |   |   |   |   |   |   |   |   |   |   Solids > 0.883745: Not Potable (1.0)
|   |   |   |   |   |   |   |   |   |   Chloramines[7,11) > 0
|   |   |   |   |   |   |   |   |   |   |   Organic_carbon[20,24) <= 0
|   |   |   |   |   |   |   |   |   |   |   |   Organic_carbon[12,16) <= 0
|   |   |   |   |   |   |   |   |   |   |   |   |   Solids <= 0.377252: Potable (1.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   Solids > 0.377252: Not Potable (4.0)
|   |   |   |   |   |   |   |   |   |   |   |   Organic_carbon[12,16) > 0
|   |   |   |   |   |   |   |   |   |   |   |   |   ph[7,11) <= 0
|   |   |   |   |   |   |   |   |   |   |   |   |   |   Solids <= 0.673943: Not Potable (3.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   |   Solids > 0.673943: Potable (1.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   ph[7,11) > 0: Potable (4.0/1.0)
|   |   |   |   |   |   |   |   |   |   |   Organic_carbon[20,24) > 0: Potable (1.0)
|   |   |   |   |   |   |   |   |   Organic_carbon[8,12) > 0
|   |   |   |   |   |   |   |   |   |   Conductivity[300,400) <= 0: Not Potable (3.0/1.0)
|   |   |   |   |   |   |   |   |   |   Conductivity[300,400) > 0: Potable (3.0)
|   |   |   |   |   |   Conductivity[500,600) > 0
|   |   |   |   |   |   |   Organic_carbon[8,12) <= 0
|   |   |   |   |   |   |   |   Organic_carbon[12,16) <= 0
|   |   |   |   |   |   |   |   |   Solids <= 0.733408: Not Potable (17.0/2.0)
|   |   |   |   |   |   |   |   |   Solids > 0.733408: Potable (1.0)
|   |   |   |   |   |   |   |   Organic_carbon[12,16) > 0
|   |   |   |   |   |   |   |   |   Trihalomethanes[80,90) <= 0: Not Potable (24.0/4.0)
|   |   |   |   |   |   |   |   |   Trihalomethanes[80,90) > 0
|   |   |   |   |   |   |   |   |   |   ph[7,11) <= 0: Not Potable (2.0)
|   |   |   |   |   |   |   |   |   |   ph[7,11) > 0: Potable (2.0)
|   |   |   |   |   |   |   Organic_carbon[8,12) > 0: Not Potable (9.0)
|   |   |   |   |   Trihalomethanes[50,60) > 0
|   |   |   |   |   |   Conductivity[500,600) <= 0
|   |   |   |   |   |   |   Organic_carbon[16,20) <= 0
|   |   |   |   |   |   |   |   Solids <= 0.638043
|   |   |   |   |   |   |   |   |   Organic_carbon[20,24) <= 0
|   |   |   |   |   |   |   |   |   |   Chloramines[7,11) <= 0
|   |   |   |   |   |   |   |   |   |   |   Turbidity[3,5) <= 0
|   |   |   |   |   |   |   |   |   |   |   |   ph[7,11) <= 0: Potable (2.0)
|   |   |   |   |   |   |   |   |   |   |   |   ph[7,11) > 0: Not Potable (1.0)
|   |   |   |   |   |   |   |   |   |   |   Turbidity[3,5) > 0
|   |   |   |   |   |   |   |   |   |   |   |   ph[7,11) <= 0: Not Potable (10.0/2.0)
|   |   |   |   |   |   |   |   |   |   |   |   ph[7,11) > 0
|   |   |   |   |   |   |   |   |   |   |   |   |   Solids <= 0.413997: Not Potable (2.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   Solids > 0.413997
|   |   |   |   |   |   |   |   |   |   |   |   |   |   Solids <= 0.461826: Potable (2.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   |   Solids > 0.461826: Not Potable (1.0)
|   |   |   |   |   |   |   |   |   |   Chloramines[7,11) > 0
|   |   |   |   |   |   |   |   |   |   |   Conductivity[400,500) <= 0
|   |   |   |   |   |   |   |   |   |   |   |   ph[7,11) <= 0
|   |   |   |   |   |   |   |   |   |   |   |   |   Organic_carbon[8,12) <= 0: Potable (3.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   Organic_carbon[8,12) > 0: Not Potable (3.0)
|   |   |   |   |   |   |   |   |   |   |   |   ph[7,11) > 0
|   |   |   |   |   |   |   |   |   |   |   |   |   Solids <= 0.622257: Potable (2.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   Solids > 0.622257: Not Potable (1.0)
|   |   |   |   |   |   |   |   |   |   |   Conductivity[400,500) > 0
|   |   |   |   |   |   |   |   |   |   |   |   Organic_carbon[8,12) <= 0
|   |   |   |   |   |   |   |   |   |   |   |   |   Turbidity[3,5) <= 0: Not Potable (2.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   Turbidity[3,5) > 0
|   |   |   |   |   |   |   |   |   |   |   |   |   |   ph[7,11) <= 0
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   Solids <= 0.475691: Not Potable (3.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   Solids > 0.475691: Potable (1.0)
|   |   |   |   |   |   |   |   |   |   |   |   |   |   ph[7,11) > 0: Potable (1.0)
|   |   |   |   |   |   |   |   |   |   |   |   Organic_carbon[8,12) > 0: Potable (2.0)
|   |   |   |   |   |   |   |   |   Organic_carbon[20,24) > 0: Not Potable (2.0)
|   |   |   |   |   |   |   |   Solids > 0.638043: Not Potable (9.0)
|   |   |   |   |   |   |   Organic_carbon[16,20) > 0
|   |   |   |   |   |   |   |   Chloramines[7,11) <= 0: Not Potable (9.0/3.0)
|   |   |   |   |   |   |   |   Chloramines[7,11) > 0
|   |   |   |   |   |   |   |   |   Conductivity[300,400) <= 0
|   |   |   |   |   |   |   |   |   |   ph[7,11) <= 0: Potable (2.0)
|   |   |   |   |   |   |   |   |   |   ph[7,11) > 0: Not Potable (2.0)
|   |   |   |   |   |   |   |   |   Conductivity[300,400) > 0: Potable (3.0)
|   |   |   |   |   |   Conductivity[500,600) > 0
|   |   |   |   |   |   |   Turbidity[3,5) <= 0: Not Potable (2.0)
|   |   |   |   |   |   |   Turbidity[3,5) > 0
|   |   |   |   |   |   |   |   Organic_carbon[20,24) <= 0
|   |   |   |   |   |   |   |   |   Organic_carbon[12,16) <= 0
|   |   |   |   |   |   |   |   |   |   ph[7,11) <= 0: Not Potable (2.0)
|   |   |   |   |   |   |   |   |   |   ph[7,11) > 0: Potable (3.0/1.0)
|   |   |   |   |   |   |   |   |   Organic_carbon[12,16) > 0
|   |   |   |   |   |   |   |   |   |   Solids <= 0.426479: Not Potable (1.0)
|   |   |   |   |   |   |   |   |   |   Solids > 0.426479: Potable (3.0)
|   |   |   |   |   |   |   |   Organic_carbon[20,24) > 0: Potable (1.0)
|   |   |   Trihalomethanes[90,100) > 0
|   |   |   |   Conductivity[300,400) <= 0
|   |   |   |   |   Solids <= 0.707437
|   |   |   |   |   |   Organic_carbon[16,20) <= 0
|   |   |   |   |   |   |   Conductivity[400,500) <= 0
|   |   |   |   |   |   |   |   Solids <= 0.300286: Not Potable (1.0)
|   |   |   |   |   |   |   |   Solids > 0.300286: Potable (3.0)
|   |   |   |   |   |   |   Conductivity[400,500) > 0
|   |   |   |   |   |   |   |   Solids <= 0.269225: Potable (2.0)
|   |   |   |   |   |   |   |   Solids > 0.269225
|   |   |   |   |   |   |   |   |   Solids <= 0.593855: Not Potable (4.0)
|   |   |   |   |   |   |   |   |   Solids > 0.593855: Potable (1.0)
|   |   |   |   |   |   Organic_carbon[16,20) > 0: Potable (6.0/1.0)
|   |   |   |   |   Solids > 0.707437: Not Potable (4.0)
|   |   |   |   Conductivity[300,400) > 0: Not Potable (10.0/2.0)
|   |   Hardness[240,280) > 0
|   |   |   ph[7,11) <= 0
|   |   |   |   Trihalomethanes[30,40) <= 0
|   |   |   |   |   Trihalomethanes[60,70) <= 0: Potable (9.0/1.0)
|   |   |   |   |   Trihalomethanes[60,70) > 0: Not Potable (6.0/2.0)
|   |   |   |   Trihalomethanes[30,40) > 0: Not Potable (1.0)
|   |   |   ph[7,11) > 0
|   |   |   |   Trihalomethanes[60,70) <= 0
|   |   |   |   |   Turbidity[5,7) <= 0
|   |   |   |   |   |   Chloramines[7,11) <= 0
|   |   |   |   |   |   |   Solids <= 0.48065: Not Potable (8.0)
|   |   |   |   |   |   |   Solids > 0.48065
|   |   |   |   |   |   |   |   Trihalomethanes[70,80) <= 0: Potable (3.0)
|   |   |   |   |   |   |   |   Trihalomethanes[70,80) > 0: Not Potable (1.0)
|   |   |   |   |   |   Chloramines[7,11) > 0
|   |   |   |   |   |   |   Conductivity[300,400) <= 0
|   |   |   |   |   |   |   |   Trihalomethanes[40,50) <= 0: Potable (4.0)
|   |   |   |   |   |   |   |   Trihalomethanes[40,50) > 0: Not Potable (1.0)
|   |   |   |   |   |   |   Conductivity[300,400) > 0: Not Potable (1.0)
|   |   |   |   |   Turbidity[5,7) > 0: Not Potable (2.0)
|   |   |   |   Trihalomethanes[60,70) > 0: Not Potable (2.0)
Sulfate[396,440) > 0
|   Trihalomethanes[90,100) <= 0
|   |   ph[7,11) <= 0
|   |   |   Chloramines[7,11) <= 0
|   |   |   |   Trihalomethanes[80,90) <= 0
|   |   |   |   |   Trihalomethanes[50,60) <= 0
|   |   |   |   |   |   Turbidity[3,5) <= 0: Not Potable (1.0)
|   |   |   |   |   |   Turbidity[3,5) > 0: Potable (11.0/1.0)
|   |   |   |   |   Trihalomethanes[50,60) > 0: Not Potable (2.0)
|   |   |   |   Trihalomethanes[80,90) > 0: Not Potable (3.0)
|   |   |   Chloramines[7,11) > 0: Potable (24.0/2.0)
|   |   ph[7,11) > 0
|   |   |   Turbidity[5,7) <= 0
|   |   |   |   Trihalomethanes[50,60) <= 0
|   |   |   |   |   Trihalomethanes[40,50) <= 0
|   |   |   |   |   |   Hardness[200,240) <= 0: Not Potable (14.0/1.0)
|   |   |   |   |   |   Hardness[200,240) > 0
|   |   |   |   |   |   |   Chloramines[7,11) <= 0: Not Potable (6.0/1.0)
|   |   |   |   |   |   |   Chloramines[7,11) > 0: Potable (4.0)
|   |   |   |   |   Trihalomethanes[40,50) > 0
|   |   |   |   |   |   Hardness[160,200) <= 0: Not Potable (1.0)
|   |   |   |   |   |   Hardness[160,200) > 0: Potable (2.0)
|   |   |   |   Trihalomethanes[50,60) > 0
|   |   |   |   |   Conductivity[400,500) <= 0: Potable (3.0)
|   |   |   |   |   Conductivity[400,500) > 0
|   |   |   |   |   |   Turbidity[3,5) <= 0: Potable (1.0)
|   |   |   |   |   |   Turbidity[3,5) > 0: Not Potable (2.0)
|   |   |   Turbidity[5,7) > 0: Not Potable (2.0)
|   Trihalomethanes[90,100) > 0: Not Potable (4.0)

Number of Leaves  :     437

Size of the tree :  873
pred_probs <- predict(C45Fit, newdata = wp)
re<-table(pred_probs ,wp$Potability)

r <- confusionMatrix(re)
acc <- r$overall["Accuracy"]*100
acc
Accuracy 
92.22857 
as.matrix(r, what = "classes")
                          [,1]
Sensitivity          0.9596623
Specificity          0.8640351
Pos Pred Value       0.9166667
Neg Pred Value       0.9321767
Precision            0.9166667
Recall               0.9596623
F1                   0.9376719
Prevalence           0.6091429
Detection Rate       0.5845714
Detection Prevalence 0.6377143
Balanced Accuracy    0.9118487
print(r)
Confusion Matrix and Statistics

             
pred_probs    Not Potable Potable
  Not Potable        1023      93
  Potable              43     591
                                          
               Accuracy : 0.9223          
                 95% CI : (0.9087, 0.9344)
    No Information Rate : 0.6091          
    P-Value [Acc > NIR] : < 2.2e-16       
                                          
                  Kappa : 0.8346          
                                          
 Mcnemar's Test P-Value : 2.649e-05       
                                          
            Sensitivity : 0.9597          
            Specificity : 0.8640          
         Pos Pred Value : 0.9167          
         Neg Pred Value : 0.9322          
             Prevalence : 0.6091          
         Detection Rate : 0.5846          
   Detection Prevalence : 0.6377          
      Balanced Accuracy : 0.9118          
                                          
       'Positive' Class : Not Potable     
                                          
pred_probs <- predict(C45Fit, newdata = wp, type = "prob")[, "Potable"]
binary_outcome <- as.numeric(wp$Potability == "Potable")
# ROC curve
roc_curve <- roc(binary_outcome, pred_probs)
Setting levels: control = 0, case = 1
Setting direction: controls < cases
plot(roc_curve, main = "ROC Curve", col = "blue", lwd = 2)
abline(a = 0, b = 1, col = "gray", lty = 2)

# Print AUC
cat("AUC:", auc(roc_curve), "\n")
AUC: 0.9692406 

C5.0 newer version of C4.5 Splitting the data set into two subsets: Training(70%) and Testing(30%):

set.seed(1958)
train.indices <- sample(2, nrow(water_potability), replace=TRUE, prob=c(0.7, 0.3))
w.train <- water_potability[train.indices == 1, ]
w.test <- water_potability[train.indices == 2, ]
w.train$Potability <- as.factor(w.train$Potability)

model <- C5.0(Potability ~., data=w.train)

results <- predict(object=model, newdata=w.test, type="class")

table(results, w.test$Potability)
             
results       Not Potable Potable
  Not Potable         290     195
  Potable              21      21
plot(model)

plot(model,type='simple')


r <- confusionMatrix(results, w.test$Potability)
acc <- r$overall["Accuracy"]*100
acc
Accuracy 
59.01328 
as.matrix(r, what = "classes")
                           [,1]
Sensitivity          0.93247588
Specificity          0.09722222
Pos Pred Value       0.59793814
Neg Pred Value       0.50000000
Precision            0.59793814
Recall               0.93247588
F1                   0.72864322
Prevalence           0.59013283
Detection Rate       0.55028463
Detection Prevalence 0.92030361
Balanced Accuracy    0.51484905
print(r)
Confusion Matrix and Statistics

             Reference
Prediction    Not Potable Potable
  Not Potable         290     195
  Potable              21      21
                                          
               Accuracy : 0.5901          
                 95% CI : (0.5468, 0.6325)
    No Information Rate : 0.5901          
    P-Value [Acc > NIR] : 0.5187          
                                          
                  Kappa : 0.0339          
                                          
 Mcnemar's Test P-Value : <2e-16          
                                          
            Sensitivity : 0.93248         
            Specificity : 0.09722         
         Pos Pred Value : 0.59794         
         Neg Pred Value : 0.50000         
             Prevalence : 0.59013         
         Detection Rate : 0.55028         
   Detection Prevalence : 0.92030         
      Balanced Accuracy : 0.51485         
                                          
       'Positive' Class : Not Potable     
                                          
pred_probs <- predict(model, newdata = w.test, type = "prob")[, "Potable"]
binary_outcome <- as.numeric(w.test$Potability == "Potable")
# ROC curve
roc_curve <- roc(binary_outcome, pred_probs)
Setting levels: control = 0, case = 1
Setting direction: controls < cases
plot(roc_curve, main = "ROC Curve", col = "blue", lwd = 2)
abline(a = 0, b = 1, col = "gray", lty = 2)

# Print AUC
cat("AUC:", auc(roc_curve), "\n")
AUC: 0.515318 

Splitting the data set into two subsets: Training(80%) and Testing(20%):

set.seed(1958)
train.indices <- sample(2, nrow(water_potability), replace=TRUE, prob=c(0.8, 0.2))
w.train <- water_potability[train.indices == 1, ]
w.test <- water_potability[train.indices == 2, ]
w.train$Potability <- as.factor(w.train$Potability)


model <- C5.0(Potability ~., data=w.train)

results <- predict(object=model, newdata=w.test, type="class")

table(results, w.test$Potability)
             
results       Not Potable Potable
  Not Potable         189     143
  Potable              11      14
plot(model)

plot(model,type='simple')


r <- confusionMatrix(results, w.test$Potability)
acc <- r$overall["Accuracy"]*100
acc
Accuracy 
56.86275 
as.matrix(r, what = "classes")
                           [,1]
Sensitivity          0.94500000
Specificity          0.08917197
Pos Pred Value       0.56927711
Neg Pred Value       0.56000000
Precision            0.56927711
Recall               0.94500000
F1                   0.71052632
Prevalence           0.56022409
Detection Rate       0.52941176
Detection Prevalence 0.92997199
Balanced Accuracy    0.51708599
print(r)
Confusion Matrix and Statistics

             Reference
Prediction    Not Potable Potable
  Not Potable         189     143
  Potable              11      14
                                          
               Accuracy : 0.5686          
                 95% CI : (0.5155, 0.6206)
    No Information Rate : 0.5602          
    P-Value [Acc > NIR] : 0.3957          
                                          
                  Kappa : 0.0376          
                                          
 Mcnemar's Test P-Value : <2e-16          
                                          
            Sensitivity : 0.94500         
            Specificity : 0.08917         
         Pos Pred Value : 0.56928         
         Neg Pred Value : 0.56000         
             Prevalence : 0.56022         
         Detection Rate : 0.52941         
   Detection Prevalence : 0.92997         
      Balanced Accuracy : 0.51709         
                                          
       'Positive' Class : Not Potable     
                                          
pred_probs <- predict(model, newdata = w.test, type = "prob")[, "Potable"]
binary_outcome <- as.numeric(w.test$Potability == "Potable")
# ROC curve
roc_curve <- roc(binary_outcome, pred_probs)
Setting levels: control = 0, case = 1
Setting direction: controls < cases
plot(roc_curve, main = "ROC Curve", col = "blue", lwd = 2)
abline(a = 0, b = 1, col = "gray", lty = 2)

# Print AUC
cat("AUC:", auc(roc_curve), "\n")
AUC: 0.5175796 

Splitting the data set into two subsets: Training(90%) and Testing(10%):

set.seed(1958)
train.indices <- sample(2, nrow(water_potability), replace=TRUE, prob=c(0.9, 0.1))
w.train <- water_potability[train.indices == 1, ]
w.test <- water_potability[train.indices == 2, ]
w.train$Potability <- as.factor(w.train$Potability)


model <- C5.0(Potability ~., data=w.train)

results <- predict(object=model, newdata=w.test, type="class")

table(results, w.test$Potability)
             
results       Not Potable Potable
  Not Potable          92      48
  Potable              12      25
plot(model)

plot(model,type='simple')


r <- confusionMatrix(results, w.test$Potability)
acc <- r$overall["Accuracy"]*100
acc
Accuracy 
66.10169 
as.matrix(r, what = "classes")
                          [,1]
Sensitivity          0.8846154
Specificity          0.3424658
Pos Pred Value       0.6571429
Neg Pred Value       0.6756757
Precision            0.6571429
Recall               0.8846154
F1                   0.7540984
Prevalence           0.5875706
Detection Rate       0.5197740
Detection Prevalence 0.7909605
Balanced Accuracy    0.6135406
print(r)
Confusion Matrix and Statistics

             Reference
Prediction    Not Potable Potable
  Not Potable          92      48
  Potable              12      25
                                          
               Accuracy : 0.661           
                 95% CI : (0.5862, 0.7303)
    No Information Rate : 0.5876          
    P-Value [Acc > NIR] : 0.02722         
                                          
                  Kappa : 0.2451          
                                          
 Mcnemar's Test P-Value : 6.228e-06       
                                          
            Sensitivity : 0.8846          
            Specificity : 0.3425          
         Pos Pred Value : 0.6571          
         Neg Pred Value : 0.6757          
             Prevalence : 0.5876          
         Detection Rate : 0.5198          
   Detection Prevalence : 0.7910          
      Balanced Accuracy : 0.6135          
                                          
       'Positive' Class : Not Potable     
                                          
pred_probs <- predict(model, newdata = w.test, type = "prob")[, "Potable"]
binary_outcome <- as.numeric(w.test$Potability == "Potable")
# ROC curve
roc_curve <- roc(binary_outcome, pred_probs)
Setting levels: control = 0, case = 1
Setting direction: controls < cases
plot(roc_curve, main = "ROC Curve", col = "blue", lwd = 2)
abline(a = 0, b = 1, col = "gray", lty = 2)

# Print AUC
cat("AUC:", auc(roc_curve), "\n")
AUC: 0.6566122 

To improve the readability of the decision tree, we decided to sample the data using only the pH and sulfate attributes. We then split the data into training and testing sets using the same split points: Training(90%) and Testing(10%), which allowed for a more manageable decision tree:

set.seed(1958)
importent_feature_sample <- select(water_potability,c(1,5,10))
train.indices <- sample(2, nrow(importent_feature_sample), replace=TRUE, prob=c(0.9, 0.1))
w.train <- importent_feature_sample[train.indices == 1, ]
w.test <- importent_feature_sample[train.indices == 2, ]
w.train$Potability <- as.factor(w.train$Potability)


model <- C5.0(Potability ~., data=w.train)

results <- predict(object=model, newdata=w.test, type="class")

table(results, w.test$Potability)
             
results       Not Potable Potable
  Not Potable          92      55
  Potable              12      18
plot(model)

plot(model,type='simple')


r <- confusionMatrix(results, w.test$Potability)
acc <- r$overall["Accuracy"]*100
acc
Accuracy 
62.14689 
as.matrix(r, what = "classes")
                          [,1]
Sensitivity          0.8846154
Specificity          0.2465753
Pos Pred Value       0.6258503
Neg Pred Value       0.6000000
Precision            0.6258503
Recall               0.8846154
F1                   0.7330677
Prevalence           0.5875706
Detection Rate       0.5197740
Detection Prevalence 0.8305085
Balanced Accuracy    0.5655954
print(r)
Confusion Matrix and Statistics

             Reference
Prediction    Not Potable Potable
  Not Potable          92      55
  Potable              12      18
                                          
               Accuracy : 0.6215          
                 95% CI : (0.5456, 0.6932)
    No Information Rate : 0.5876          
    P-Value [Acc > NIR] : 0.2009          
                                          
                  Kappa : 0.1438          
                                          
 Mcnemar's Test P-Value : 2.88e-07        
                                          
            Sensitivity : 0.8846          
            Specificity : 0.2466          
         Pos Pred Value : 0.6259          
         Neg Pred Value : 0.6000          
             Prevalence : 0.5876          
         Detection Rate : 0.5198          
   Detection Prevalence : 0.8305          
      Balanced Accuracy : 0.5656          
                                          
       'Positive' Class : Not Potable     
                                          
pred_probs <- predict(model, newdata = w.test, type = "prob")[, "Potable"]
binary_outcome <- as.numeric(w.test$Potability == "Potable")
# ROC curve
roc_curve <- roc(binary_outcome, pred_probs)
Setting levels: control = 0, case = 1
Setting direction: controls < cases
plot(roc_curve, main = "ROC Curve", col = "blue", lwd = 2)
abline(a = 0, b = 1, col = "gray", lty = 2)

# Print AUC
cat("AUC:", auc(roc_curve), "\n")
AUC: 0.5474842 

we employed the C5.0 algorithm, an enhanced version of the C4.5 decision tree, for model training and evaluation across different training and testing set splits. The dataset underwent three scenarios: Training(70%) and Testing(30%), Training(80%) and Testing(20%), and Training(90%) and Testing(10%). For each case, the C5.0 model was trained on the designated training data, evaluated on the testing data, and its performance was assessed through accuracy, confusion matrix, and ROC curve with Area Under the Curve (AUC).

Upon comparative analysis, it was observed that the model trained with a larger proportion of data (Training 90%, Testing 10%) demonstrated superior performance, achieving higher accuracy and a more discriminative ROC curve. This exploration across different training and testing splits provides valuable insights into the robustness and generalization capability of the C5.0 decision tree algorithm for predicting water potability.

Gini index (CART)

Splitting the data set into two subsets: Training(70%) and Testing(30%):

set.seed(1958)
train = sample(2, nrow(wp), replace=TRUE, prob=c(0.7, 0.3))
wp.train=wp[train == 1,]
wp.test=wp[train == 2,]



fit.tree = rpart(Potability ~ ., data=wp, method = "class", cp=0.008)
fit.tree
n= 1750 

node), split, n, loss, yval, (yprob)
      * denotes terminal node

 1) root 1750 684 Not Potable (0.6091429 0.3908571)  
   2) Sulfate=[308,352) 806 263 Not Potable (0.6736973 0.3263027) *
   3) Sulfate=[220,264),[264,308),[352,396),[396,440) 944 421 Not Potable (0.5540254 0.4459746)  
     6) Sulfate=[264,308),[352,396) 819 349 Not Potable (0.5738706 0.4261294)  
      12) Solids< 0.7847186 758 312 Not Potable (0.5883905 0.4116095) *
      13) Solids>=0.7847186 61  24 Potable (0.3934426 0.6065574) *
     7) Sulfate=[220,264),[396,440) 125  53 Potable (0.4240000 0.5760000) *
rpart.plot(fit.tree)


fit.tree$variable.importance
        Sulfate          Solids Trihalomethanes 
    17.32500374      4.33758572      0.04635208 
pred.tree = predict(fit.tree, wp.test, type = "class")
re <- table(pred.tree, wp.test$Potability)

co_re <- confusionMatrix(re)
print(co_re)
Confusion Matrix and Statistics

             
pred.tree     Not Potable Potable
  Not Potable         285     185
  Potable              26      31
                                          
               Accuracy : 0.5996          
                 95% CI : (0.5564, 0.6417)
    No Information Rate : 0.5901          
    P-Value [Acc > NIR] : 0.3459          
                                          
                  Kappa : 0.0675          
                                          
 Mcnemar's Test P-Value : <2e-16          
                                          
            Sensitivity : 0.9164          
            Specificity : 0.1435          
         Pos Pred Value : 0.6064          
         Neg Pred Value : 0.5439          
             Prevalence : 0.5901          
         Detection Rate : 0.5408          
   Detection Prevalence : 0.8918          
      Balanced Accuracy : 0.5300          
                                          
       'Positive' Class : Not Potable     
                                          
as.matrix(co_re, what = "classes")
                          [,1]
Sensitivity          0.9163987
Specificity          0.1435185
Pos Pred Value       0.6063830
Neg Pred Value       0.5438596
Precision            0.6063830
Recall               0.9163987
F1                   0.7298335
Prevalence           0.5901328
Detection Rate       0.5407970
Detection Prevalence 0.8918406
Balanced Accuracy    0.5299586
acc <- co_re$overall["Accuracy"]
acc*100
Accuracy 
59.96205 
plotcp(fit.tree)

printcp(fit.tree)

Classification tree:
rpart(formula = Potability ~ ., data = wp, method = "class", 
    cp = 0.008)

Variables actually used in tree construction:
[1] Solids  Sulfate

Root node error: 684/1750 = 0.39086

n= 1750 

        CP nsplit rel error  xerror     xstd
1 0.013889      0   1.00000 1.00000 0.029842
2 0.008000      3   0.95322 0.97368 0.029695
# Explicitly request the lowest cp value
fit.tree$cptable[which.min(fit.tree$cptable[,"xerror"]),"CP"]
[1] 0.008
bestcp <-fit.tree$cptable[which.min(fit.tree$cptable[,"xerror"]),"CP"]
pruned.tree <- prune(fit.tree, cp = bestcp)
rpart.plot(pruned.tree)


pred.prune = predict(pruned.tree, wp.test, type="class")

re <- table(pred.prune, wp.test$Potability)

co_re <- confusionMatrix(re)
print(co_re)
Confusion Matrix and Statistics

             
pred.prune    Not Potable Potable
  Not Potable         285     185
  Potable              26      31
                                          
               Accuracy : 0.5996          
                 95% CI : (0.5564, 0.6417)
    No Information Rate : 0.5901          
    P-Value [Acc > NIR] : 0.3459          
                                          
                  Kappa : 0.0675          
                                          
 Mcnemar's Test P-Value : <2e-16          
                                          
            Sensitivity : 0.9164          
            Specificity : 0.1435          
         Pos Pred Value : 0.6064          
         Neg Pred Value : 0.5439          
             Prevalence : 0.5901          
         Detection Rate : 0.5408          
   Detection Prevalence : 0.8918          
      Balanced Accuracy : 0.5300          
                                          
       'Positive' Class : Not Potable     
                                          
as.matrix(co_re, what = "classes")
                          [,1]
Sensitivity          0.9163987
Specificity          0.1435185
Pos Pred Value       0.6063830
Neg Pred Value       0.5438596
Precision            0.6063830
Recall               0.9163987
F1                   0.7298335
Prevalence           0.5901328
Detection Rate       0.5407970
Detection Prevalence 0.8918406
Balanced Accuracy    0.5299586
acc <- co_re$overall["Accuracy"]
acc*100
Accuracy 
59.96205 
pred.tree_raw <- predict(fit.tree, wp.test)
# Convert to probabilities
pred.tree_probs <- exp(pred.tree_raw) / (1 + exp(pred.tree_raw))
# Extract probabilities for the "Potable" class
roc_curve <- roc(ifelse(wp.test$Potability == "Potable", 1, 0), pred.tree_probs[, "Potable"])
Setting levels: control = 0, case = 1
Setting direction: controls < cases
plot(roc_curve, main = "ROC Curve", col = "blue", lwd = 2)
abline(a = 0, b = 1, col = "gray", lty = 2)

# Print AUC
cat("AUC:", auc(roc_curve), "\n")
AUC: 0.5769769 

Splitting the data set into two subsets: Training(80%) and Testing(20%):

set.seed(1958)
train = sample(2, nrow(wp), replace=TRUE, prob=c(0.8, 0.2))
wp.train=wp[train == 1,]
wp.test=wp[train == 2,]



fit.tree = rpart(Potability ~ ., data=wp.train, method = "class", cp=0.008)
fit.tree
n= 1393 

node), split, n, loss, yval, (yprob)
      * denotes terminal node

 1) root 1393 527 Not Potable (0.6216798 0.3783202)  
   2) Sulfate=[308,352) 651 205 Not Potable (0.6850998 0.3149002) *
   3) Sulfate=[220,264),[264,308),[352,396),[396,440) 742 322 Not Potable (0.5660377 0.4339623)  
     6) Solids< 0.6416071 598 240 Not Potable (0.5986622 0.4013378)  
      12) Sulfate=[264,308),[352,396) 519 197 Not Potable (0.6204239 0.3795761) *
      13) Sulfate=[220,264),[396,440) 79  36 Potable (0.4556962 0.5443038)  
        26) Trihalomethanes=[20,30),[30,40),[80,90),[90,100) 18   6 Not Potable (0.6666667 0.3333333) *
        27) Trihalomethanes=[40,50),[50,60),[60,70),[70,80),[100,110) 61  24 Potable (0.3934426 0.6065574)  
          54) Solids< 0.2515644 11   3 Not Potable (0.7272727 0.2727273) *
          55) Solids>=0.2515644 50  16 Potable (0.3200000 0.6800000) *
     7) Solids>=0.6416071 144  62 Potable (0.4305556 0.5694444)  
      14) Sulfate=[352,396),[396,440) 62  24 Not Potable (0.6129032 0.3870968)  
        28) Trihalomethanes=[30,40),[40,50),[60,70),[70,80) 45  13 Not Potable (0.7111111 0.2888889) *
        29) Trihalomethanes=[50,60),[80,90),[100,110) 17   6 Potable (0.3529412 0.6470588) *
      15) Sulfate=[220,264),[264,308) 82  24 Potable (0.2926829 0.7073171)  
        30) ph=[3,7) 32  16 Not Potable (0.5000000 0.5000000)  
          60) Chloramines=[7,11) 15   3 Not Potable (0.8000000 0.2000000) *
          61) Chloramines=[3,7) 17   4 Potable (0.2352941 0.7647059) *
        31) ph=[7,11) 50   8 Potable (0.1600000 0.8400000) *
rpart.plot(fit.tree)


fit.tree$variable.importance
        Sulfate          Solids Trihalomethanes     Chloramines              ph        Hardness  Organic_carbon 
     21.4704559      11.1997162       8.3888087       5.0823529       4.5112195       0.9695811       0.9263146 
   Conductivity 
      0.5397097 
pred.tree = predict(fit.tree, wp.test, type = "class")
re <- table(pred.tree, wp.test$Potability)

co_re <- confusionMatrix(re)
print(co_re)
Confusion Matrix and Statistics

             
pred.tree     Not Potable Potable
  Not Potable         184     138
  Potable              16      19
                                          
               Accuracy : 0.5686          
                 95% CI : (0.5155, 0.6206)
    No Information Rate : 0.5602          
    P-Value [Acc > NIR] : 0.3957          
                                          
                  Kappa : 0.0448          
                                          
 Mcnemar's Test P-Value : <2e-16          
                                          
            Sensitivity : 0.9200          
            Specificity : 0.1210          
         Pos Pred Value : 0.5714          
         Neg Pred Value : 0.5429          
             Prevalence : 0.5602          
         Detection Rate : 0.5154          
   Detection Prevalence : 0.9020          
      Balanced Accuracy : 0.5205          
                                          
       'Positive' Class : Not Potable     
                                          
as.matrix(co_re, what = "classes")
                          [,1]
Sensitivity          0.9200000
Specificity          0.1210191
Pos Pred Value       0.5714286
Neg Pred Value       0.5428571
Precision            0.5714286
Recall               0.9200000
F1                   0.7049808
Prevalence           0.5602241
Detection Rate       0.5154062
Detection Prevalence 0.9019608
Balanced Accuracy    0.5205096
acc <- co_re$overall["Accuracy"]
acc*100
Accuracy 
56.86275 
plotcp(fit.tree)

printcp(fit.tree)

Classification tree:
rpart(formula = Potability ~ ., data = wp.train, method = "class", 
    cp = 0.008)

Variables actually used in tree construction:
[1] Chloramines     ph              Solids          Sulfate         Trihalomethanes

Root node error: 527/1393 = 0.37832

n= 1393 

         CP nsplit rel error  xerror     xstd
1 0.0189753      0   1.00000 1.00000 0.034346
2 0.0132827      3   0.93548 0.97913 0.034201
3 0.0113852      4   0.92220 0.98102 0.034215
4 0.0094877      5   0.91082 0.99810 0.034333
5 0.0085389      7   0.89184 0.99051 0.034281
6 0.0080000      9   0.87476 0.98102 0.034215
# Explicitly request the lowest cp value
fit.tree$cptable[which.min(fit.tree$cptable[,"xerror"]),"CP"]
[1] 0.01328273
bestcp <-fit.tree$cptable[which.min(fit.tree$cptable[,"xerror"]),"CP"]
pruned.tree <- prune(fit.tree, cp = bestcp)
rpart.plot(pruned.tree)


pred.prune = predict(pruned.tree, wp.test, type="class")

re <- table(pred.prune, wp.test$Potability)

co_re <- confusionMatrix(re)
print(co_re)
Confusion Matrix and Statistics

             
pred.prune    Not Potable Potable
  Not Potable         190     141
  Potable              10      16
                                          
               Accuracy : 0.577           
                 95% CI : (0.5239, 0.6289)
    No Information Rate : 0.5602          
    P-Value [Acc > NIR] : 0.2793          
                                          
                  Kappa : 0.057           
                                          
 Mcnemar's Test P-Value : <2e-16          
                                          
            Sensitivity : 0.9500          
            Specificity : 0.1019          
         Pos Pred Value : 0.5740          
         Neg Pred Value : 0.6154          
             Prevalence : 0.5602          
         Detection Rate : 0.5322          
   Detection Prevalence : 0.9272          
      Balanced Accuracy : 0.5260          
                                          
       'Positive' Class : Not Potable     
                                          
as.matrix(co_re, what = "classes")
                          [,1]
Sensitivity          0.9500000
Specificity          0.1019108
Pos Pred Value       0.5740181
Neg Pred Value       0.6153846
Precision            0.5740181
Recall               0.9500000
F1                   0.7156309
Prevalence           0.5602241
Detection Rate       0.5322129
Detection Prevalence 0.9271709
Balanced Accuracy    0.5259554
acc <- co_re$overall["Accuracy"]
acc*100
Accuracy 
57.70308 
pred.tree_raw <- predict(fit.tree, wp.test)
pred.tree_probs <- exp(pred.tree_raw) / (1 + exp(pred.tree_raw))
roc_curve <- roc(ifelse(wp.test$Potability == "Potable", 1, 0), pred.tree_probs[, "Potable"])
Setting levels: control = 0, case = 1
Setting direction: controls < cases
plot(roc_curve, main = "ROC Curve", col = "blue", lwd = 2)
abline(a = 0, b = 1, col = "gray", lty = 2)

# Print AUC
cat("AUC:", auc(roc_curve), "\n")
AUC: 0.5796656 

Splitting the data set into two subsets: Training(90%) and Testing(10%):

set.seed(1958)
train = sample(2, nrow(wp), replace=TRUE, prob=c(0.9, 0.1))
wp.train=wp[train == 1,]
wp.test=wp[train == 2,]



fit.tree = rpart(Potability ~ ., data=wp.train, method = "class", cp=0.008)
fit.tree
n= 1573 

node), split, n, loss, yval, (yprob)
      * denotes terminal node

 1) root 1573 611 Not Potable (0.6115702 0.3884298)  
   2) Sulfate=[308,352) 733 236 Not Potable (0.6780355 0.3219645) *
   3) Sulfate=[220,264),[264,308),[352,396),[396,440) 840 375 Not Potable (0.5535714 0.4464286)  
     6) Solids< 0.6665636 704 294 Not Potable (0.5823864 0.4176136)  
      12) Sulfate=[264,308),[352,396) 618 245 Not Potable (0.6035599 0.3964401) *
      13) Sulfate=[220,264),[396,440) 86  37 Potable (0.4302326 0.5697674)  
        26) Trihalomethanes=[20,30),[30,40),[80,90),[90,100) 18   6 Not Potable (0.6666667 0.3333333) *
        27) Trihalomethanes=[40,50),[50,60),[60,70),[70,80),[100,110) 68  25 Potable (0.3676471 0.6323529) *
     7) Solids>=0.6665636 136  55 Potable (0.4044118 0.5955882)  
      14) Sulfate=[352,396),[396,440) 54  20 Not Potable (0.6296296 0.3703704) *
      15) Sulfate=[220,264),[264,308) 82  21 Potable (0.2560976 0.7439024) *
rpart.plot(fit.tree)


fit.tree$variable.importance
        Sulfate          Solids Trihalomethanes        Hardness  Organic_carbon 
    25.74920220      7.43857110      3.83872439      0.06618024      0.06618024 
pred.tree = predict(fit.tree, wp.test, type = "class")
re <- table(pred.tree, wp.test$Potability)

co_re <- confusionMatrix(re)
print(co_re)
Confusion Matrix and Statistics

             
pred.tree     Not Potable Potable
  Not Potable          92      65
  Potable              12       8
                                          
               Accuracy : 0.565           
                 95% CI : (0.4885, 0.6392)
    No Information Rate : 0.5876          
    P-Value [Acc > NIR] : 0.7547          
                                          
                  Kappa : -0.0065         
                                          
 Mcnemar's Test P-Value : 3.105e-09       
                                          
            Sensitivity : 0.8846          
            Specificity : 0.1096          
         Pos Pred Value : 0.5860          
         Neg Pred Value : 0.4000          
             Prevalence : 0.5876          
         Detection Rate : 0.5198          
   Detection Prevalence : 0.8870          
      Balanced Accuracy : 0.4971          
                                          
       'Positive' Class : Not Potable     
                                          
as.matrix(co_re, what = "classes")
                          [,1]
Sensitivity          0.8846154
Specificity          0.1095890
Pos Pred Value       0.5859873
Neg Pred Value       0.4000000
Precision            0.5859873
Recall               0.8846154
F1                   0.7049808
Prevalence           0.5875706
Detection Rate       0.5197740
Detection Prevalence 0.8870056
Balanced Accuracy    0.4971022
acc <- co_re$overall["Accuracy"]
acc*100
Accuracy 
56.49718 
plotcp(fit.tree)

printcp(fit.tree)

Classification tree:
rpart(formula = Potability ~ ., data = wp.train, method = "class", 
    cp = 0.008)

Variables actually used in tree construction:
[1] Solids          Sulfate         Trihalomethanes

Root node error: 611/1573 = 0.38843

n= 1573 

        CP nsplit rel error  xerror     xstd
1 0.021277      0   1.00000 1.00000 0.031638
2 0.019640      3   0.93453 1.04092 0.031856
3 0.009820      4   0.91489 1.00164 0.031647
4 0.008000      5   0.90507 0.99345 0.031599
# Explicitly request the lowest cp value
fit.tree$cptable[which.min(fit.tree$cptable[,"xerror"]),"CP"]
[1] 0.008
bestcp <-fit.tree$cptable[which.min(fit.tree$cptable[,"xerror"]),"CP"]
pruned.tree <- prune(fit.tree, cp = bestcp)
rpart.plot(pruned.tree)


pred.prune = predict(pruned.tree, wp.test, type="class")

re <- table(pred.prune, wp.test$Potability)

co_re <- confusionMatrix(re)
print(co_re)
Confusion Matrix and Statistics

             
pred.prune    Not Potable Potable
  Not Potable          92      65
  Potable              12       8
                                          
               Accuracy : 0.565           
                 95% CI : (0.4885, 0.6392)
    No Information Rate : 0.5876          
    P-Value [Acc > NIR] : 0.7547          
                                          
                  Kappa : -0.0065         
                                          
 Mcnemar's Test P-Value : 3.105e-09       
                                          
            Sensitivity : 0.8846          
            Specificity : 0.1096          
         Pos Pred Value : 0.5860          
         Neg Pred Value : 0.4000          
             Prevalence : 0.5876          
         Detection Rate : 0.5198          
   Detection Prevalence : 0.8870          
      Balanced Accuracy : 0.4971          
                                          
       'Positive' Class : Not Potable     
                                          
as.matrix(co_re, what = "classes")
                          [,1]
Sensitivity          0.8846154
Specificity          0.1095890
Pos Pred Value       0.5859873
Neg Pred Value       0.4000000
Precision            0.5859873
Recall               0.8846154
F1                   0.7049808
Prevalence           0.5875706
Detection Rate       0.5197740
Detection Prevalence 0.8870056
Balanced Accuracy    0.4971022
acc <- co_re$overall["Accuracy"]
acc*100
Accuracy 
56.49718 
pred.tree_raw <- predict(fit.tree, wp.test)
pred.tree_probs <- exp(pred.tree_raw) / (1 + exp(pred.tree_raw))
roc_curve <- roc(ifelse(wp.test$Potability == "Potable", 1, 0), pred.tree_probs[, "Potable"])
Setting levels: control = 0, case = 1
Setting direction: controls < cases
plot(roc_curve, main = "ROC Curve", col = "blue", lwd = 2)
abline(a = 0, b = 1, col = "gray", lty = 2)

# Print AUC
cat("AUC:", auc(roc_curve), "\n")
AUC: 0.551304 

Comparison Criteria:

For each Information Gain, Gain Ratio(5.0), and Gini index splitting the data set into two subsets:

Training(90%) and Testing(10%):
Information Gain Gain Ratio Gini index
Accuracy 56.49% 62.14% 56.50%
precision 58.71% 62.59% 58.60%
sensitivity 87.50% 88.46% 58.60%
specificity 12.33% 24.66% 10.96%
Training(80%) and Testing(20%):
Information Gain Gain Ratio Gini index
Accuracy 57.42% 56.86% 57.70%
precision 57.14% 56.93% 57.40%
sensitivity 96% 94.50% 95%
specificity 8.28% 8.92% 10.19%
Training(70%) and Testing(30%):
Information Gain Gain Ratio Gini index
Accuracy 58.63% 59.01% 59.96%
precision 59.43% 59.79% 60.64%
sensitivity 94.21% 93.25% 91.64%
specificity 7.41% 9.72% 14.35%

For Gain Ratio(4.5) with K-folds:

K=3 K=5 K=10
Accuracy 62.17% 62.17% 92.23%
precision 58.71% 61.83% 91.67%
sensitivity 99.06% 99.06% 95.97%
specificity 4.68% 4.68% 86.40%

As shown in the comparison the best technique to choose is Gain Raio Due to the high accuracy

summary(water_potability)
       ph            Hardness         Solids         Chloramines        Sulfate       Conductivity   Organic_carbon  
 Min.   : 3.388   Min.   :121.0   Min.   :  320.9   Min.   : 3.352   Min.   :237.5   Min.   :201.6   Min.   : 5.512  
 1st Qu.: 6.125   1st Qu.:177.8   1st Qu.:15465.4   1st Qu.: 6.189   1st Qu.:309.7   1st Qu.:366.4   1st Qu.:12.233  
 Median : 7.026   Median :197.3   Median :20468.8   Median : 7.135   Median :333.0   Median :422.4   Median :14.353  
 Mean   : 7.075   Mean   :196.0   Mean   :21362.1   Mean   : 7.131   Mean   :333.9   Mean   :426.0   Mean   :14.434  
 3rd Qu.: 7.986   3rd Qu.:215.0   3rd Qu.:26588.0   3rd Qu.: 8.062   3rd Qu.:357.8   3rd Qu.:482.2   3rd Qu.:16.797  
 Max.   :10.905   Max.   :272.1   Max.   :43195.5   Max.   :10.897   Max.   :429.8   Max.   :652.5   Max.   :23.604  
 Trihalomethanes    Turbidity           Potability  
 Min.   : 24.53   Min.   :1.873   Not Potable:1066  
 1st Qu.: 55.96   1st Qu.:3.443   Potable    : 684  
 Median : 66.33   Median :3.974                     
 Mean   : 66.42   Mean   :3.972                     
 3rd Qu.: 77.34   3rd Qu.:4.512                     
 Max.   :108.85   Max.   :6.084                     
str(water_potability)
'data.frame':   1750 obs. of  10 variables:
 $ ph             : num  8.32 9.09 5.58 10.22 8.64 ...
 $ Hardness       : num  214 181 188 248 203 ...
 $ Solids         : num  22018 17979 28749 28750 13672 ...
 $ Chloramines    : num  8.06 6.55 7.54 7.51 4.56 ...
 $ Sulfate        : num  357 310 327 394 303 ...
 $ Conductivity   : num  363 398 280 284 475 ...
 $ Organic_carbon : num  18.4 11.6 8.4 13.8 12.4 ...
 $ Trihalomethanes: num  100.3 32 54.9 84.6 62.8 ...
 $ Turbidity      : num  4.63 4.08 2.56 2.67 4.4 ...
 $ Potability     : Factor w/ 2 levels "Not Potable",..: 1 1 1 1 1 1 1 1 1 1 ...
 - attr(*, "na.action")= 'omit' Named int [1:1265] 1 2 3 9 12 14 15 17 19 21 ...
  ..- attr(*, "names")= chr [1:1265] "1" "2" "3" "9" ...

Clustering

determine and visualize optimal number of clusters:

We will experiment with four random sizes of k for clustering in order to find the ideal number of clusters (k) for our dataset. We will use a number of techniques (calculate average silhouette, total within-cluster sum of square, kmeansruns, and BCubed (precision and recall)) to help with this determination in order to help find the best k value for our particular dataset.

Scale data first:

Confirm that all the columns you are trying to scale are indeed numeric. You can use sapply() to check and coerce them to numeric if necessary.

sinec all coulme are numeric we wll scale all of them expet class label and we saved it in dataset called Cluster and we used it in Clustring

water_potability<- sapply(water_potability, as.numeric)

data_for_cluster <- scale(water_potability[, !colnames(water_potability) %in% "Potability"])
#we use !colnames(water_potability) %in% "Potability" to exclude the "Potability" column
View(data_for_cluster)

Clustring1

K-means

# 3- run k-means clustering to find 2 clusters
#set a seed for random number generation  to make the results reproducible
set.seed(8953)
kmeans.result <- kmeans(data_for_cluster,2)
# print the clusterng result
kmeans.result
K-means clustering with 2 clusters of sizes 837, 913

Cluster means:
          ph   Hardness     Solids Chloramines    Sulfate Conductivity Organic_carbon Trihalomethanes  Turbidity
1 -0.5572534 -0.5126443  0.4503724  0.05290412 -0.2277059  -0.01213702    0.005065769     -0.02581942  0.1808420
2  0.5108665  0.4699707 -0.4128825 -0.04850028  0.2087512   0.01112671   -0.004644084      0.02367016 -0.1657883

Clustering vector:
   [1] 2 2 1 2 2 1 1 1 2 1 1 1 1 2 2 1 1 2 1 2 2 2 2 1 2 2 2 1 1 1 2 1 1 1 1 2 2 2 1 2 2 2 2 2 1 2 1 2 1 2 2 2 1 2 2 2 1
  [58] 2 2 1 2 2 2 2 1 1 1 1 1 1 1 2 2 2 1 2 2 1 2 1 1 1 2 2 2 1 1 2 1 2 2 1 2 1 1 1 1 1 1 1 2 2 1 1 2 1 2 2 1 2 2 1 1 1
 [115] 2 2 1 1 2 2 2 2 1 1 2 1 1 2 2 2 2 2 2 2 2 1 1 2 2 2 1 2 1 2 2 1 1 1 1 2 1 1 1 1 1 2 2 2 1 1 1 2 2 1 2 1 1 2 2 1 1
 [172] 2 2 1 2 1 1 2 2 2 2 1 2 1 1 2 2 1 2 1 1 2 1 1 2 2 2 2 2 2 1 1 2 1 2 2 1 1 1 1 1 1 2 1 2 2 2 2 1 1 2 2 2 2 2 1 2 1
 [229] 1 2 1 2 2 2 2 1 1 2 2 2 2 2 1 2 2 1 1 1 2 1 2 2 1 1 2 2 1 1 2 1 1 2 1 1 2 1 1 1 1 1 2 2 2 1 1 1 1 2 1 2 2 1 2 1 1
 [286] 1 1 2 2 1 2 2 1 2 2 2 1 1 1 1 2 1 1 2 2 2 1 2 1 2 2 2 2 1 2 2 1 1 2 2 2 1 2 2 1 1 1 1 1 1 2 2 1 2 1 1 2 1 2 1 2 1
 [343] 1 2 2 1 2 2 2 1 2 2 1 2 2 2 1 2 2 1 2 2 2 2 1 2 2 1 1 1 1 1 1 1 1 2 2 1 2 2 1 1 2 2 2 2 2 2 2 2 2 2 1 1 2 2 2 2 2
 [400] 2 2 2 2 1 1 2 2 1 1 2 2 1 1 1 2 2 2 2 1 2 2 2 1 2 2 1 2 2 1 1 1 1 1 1 2 2 1 1 2 2 1 2 1 2 1 2 2 2 1 1 1 2 2 2 2 2
 [457] 2 2 1 1 2 1 1 1 1 1 2 1 2 2 1 2 1 1 2 1 1 1 2 2 2 1 1 2 1 2 2 1 2 1 2 1 2 2 1 1 1 2 1 2 1 2 2 2 2 2 1 1 2 1 2 1 2
 [514] 1 1 2 2 2 2 2 1 1 2 1 1 2 2 2 2 2 2 2 1 2 1 2 1 2 1 2 1 1 2 1 2 2 2 1 2 2 1 1 2 1 1 2 2 2 2 1 1 2 1 2 2 1 1 1 2 2
 [571] 2 1 2 2 2 1 2 2 2 2 2 2 2 2 2 2 1 1 2 2 2 2 2 2 2 1 2 1 2 2 1 2 1 2 1 1 2 1 2 2 2 1 1 1 2 1 2 1 2 1 2 1 2 1 1 2 2
 [628] 1 2 2 1 2 1 1 1 2 1 2 1 1 1 1 2 1 1 1 1 2 1 2 2 2 1 1 1 1 1 1 1 1 2 1 1 2 2 1 1 2 1 1 1 1 1 2 1 2 1 2 1 2 1 2 1 2
 [685] 1 2 2 1 1 1 1 1 2 2 1 2 1 1 1 1 1 1 1 2 1 2 1 2 2 1 1 2 2 2 2 2 2 2 1 2 1 2 1 2 1 1 2 2 2 2 1 1 2 2 1 1 1 1 2 2 2
 [742] 2 1 1 2 1 2 1 2 1 1 1 2 2 2 1 2 1 2 2 1 2 1 2 1 2 2 2 2 2 2 2 2 1 2 1 2 1 2 1 2 1 2 2 2 2 2 2 1 2 1 1 1 2 2 1 1 1
 [799] 2 2 1 1 2 2 1 1 2 2 1 1 2 2 1 1 1 1 2 2 2 2 2 2 1 1 2 2 1 1 1 2 2 1 2 1 1 1 2 2 2 1 1 1 1 2 2 2 1 2 2 1 2 2 1 1 1
 [856] 2 2 1 2 1 1 2 2 1 2 1 2 1 1 2 2 2 2 2 2 2 1 1 2 1 2 1 2 2 2 2 2 2 2 2 1 1 2 1 2 2 1 2 2 2 2 1 1 1 2 2 2 1 2 1 1 2
 [913] 1 2 1 2 2 2 2 2 1 1 2 1 2 2 1 2 2 2 2 1 2 2 1 1 1 2 1 2 2 1 2 1 1 2 2 2 2 2 2 2 1 2 1 2 1 2 2 1 1 2 2 1 1 1 1 1 2
 [970] 2 1 2 1 2 2 1 2 1 2 2 2 2 2 1 2 1 2 1 2 2 2 1 2 1 1 2 1 2 2 1
 [ reached getOption("max.print") -- omitted 750 entries ]

Within cluster sum of squares by cluster:
[1] 6888.207 7466.072
 (between_SS / total_SS =   8.8 %)

Available components:

[1] "cluster"      "centers"      "totss"        "withinss"     "tot.withinss" "betweenss"    "size"        
[8] "iter"         "ifault"      

visualize clustering

# visualize clustering (2 clusters)
fviz_cluster(kmeans.result, data = data_for_cluster)

hiercrchical clustering

we took 50 sample to make it more understabale

# draw a sample of 50 records from the data, so that the clustering plot will not be over crowded and easy to undrestand 
idx<-sample(1:dim(data_for_cluster)[1], 50)
sample_c1<-data_for_cluster[idx, ]

## hiercrchical clustering
hc.cut<- hcut(sample_c1, k = 2, hc_method= "complete")

Visualize dendrogram and sample Clustering

dendrogram is a tree diagram that displays the arrangement of data points in a hierarchical order based on their similarity or dissimilarity.

# Visualize dendrogram
fviz_dend(hc.cut,rect= TRUE)

# Visualize cluster
fviz_cluster(hc.cut, ellipse.type= "convex")

average silhouette

This method calculates the average silhouette width for different values of k, determining how well data points fit into their assigned clusters.

 #average silhouette for each clusters 

avg_sil <- silhouette(kmeans.result$cluster,dist(data_for_cluster)) #a dissimilarity object inheriting from class dist or coercible to one. If not specified, dmatrix must be.
fviz_silhouette(avg_sil)#k-means clustering with estimating k and initializations

BCubed precision and recall

BCubed precision and recall are metrics used to evaluate the performance of clustering algorithms, particularly in the context of evaluating the quality of clustering assignments for individual data points.


cluster_assignments <- c(kmeans.result$cluster)
ground_truth_labels <- c(water_potability)
data <- data.frame(cluster = cluster_assignments, label = ground_truth_labels)

# Function to calculate BCubed precision and recall
calculate_bcubed_metrics <- function(data) {
  n <- nrow(data)
  precision_sum <- 0
  recall_sum <- 0

  for (i in 1:n) {
    cluster <- data$cluster[i]
    label <- data$label[i]
    
# Count the number of items from the same category within the same cluster
same_category_same_cluster <- sum(data$label[data$cluster == cluster] == label)
    
# Count the total number of items in the same cluster
total_same_cluster <- sum(data$cluster == cluster)
    
# Count the total number of items with the same category
total_same_category <- sum(data$label == label)
    
# Calculate precision and recall for the current item and add them to the sums
precision_sum <- precision_sum + same_category_same_cluster /total_same_cluster
recall_sum <- recall_sum + same_category_same_cluster / total_same_category
  }

  # Calculate average precision and recall
  precision <- precision_sum / n
  recall <- recall_sum / n

  return(list(precision = precision, recall = recall))
}

# Calculate BCubed precision and recall
metrics <- calculate_bcubed_metrics(data)


# Extract precision and recall from the metrics
precision <- metrics$precision
recall <- metrics$recall

# Print the results
cat("BCubed Precision:", precision, "\n")
BCubed Precision: 0.005341313 
cat("BCubed Recall:", recall, "\n")
BCubed Recall: 0.9500965 

Clustring2

K-means

run k-means clustering to find 3 clusters set a seed for random number generation to make the results reproducible

set.seed(8953)
kmeans.result <- kmeans(data_for_cluster,3)
# print the Clustring result
kmeans.result
K-means clustering with 3 clusters of sizes 552, 605, 593

Cluster means:
          ph   Hardness     Solids Chloramines     Sulfate Conductivity Organic_carbon Trihalomethanes  Turbidity
1 -0.2519979 -0.5998097 -0.3779584  0.24115308  0.74974815  -0.31275082     -0.2069277      0.11328128  0.1748770
2  0.6578986  0.6735686 -0.4294630 -0.15789451 -0.05599083   0.24575664      0.0751758      0.02595442 -0.3158780
3 -0.4366371 -0.1288601  0.7899800 -0.06339008 -0.64078672   0.04039745      0.1159236     -0.13192865  0.1594841

Clustering vector:
   [1] 2 2 3 2 2 3 3 3 2 3 1 1 3 1 2 3 3 2 1 1 2 2 2 3 2 2 2 1 3 3 2 3 3 3 3 1 2 2 3 3 2 2 2 2 3 1 3 2 3 2 2 2 1 2 2 2 1
  [58] 2 2 3 2 2 1 2 3 3 3 3 3 1 1 2 2 2 3 2 2 1 1 3 3 1 2 2 2 1 1 1 2 3 2 3 2 3 1 3 3 1 3 1 1 2 2 3 2 3 3 2 2 2 2 1 1 3
 [115] 2 2 3 2 2 2 2 2 3 3 2 3 1 2 2 2 1 2 2 1 1 1 3 2 3 2 3 2 1 2 1 3 3 3 3 2 1 3 3 3 3 2 1 2 1 3 3 1 2 3 3 3 1 2 1 3 1
 [172] 2 2 3 1 1 3 1 1 1 2 1 2 1 1 2 3 3 1 3 3 2 3 1 1 2 2 2 2 2 3 3 1 3 2 2 1 3 3 3 3 3 2 3 2 2 2 1 3 1 2 1 2 2 2 3 2 3
 [229] 1 2 3 2 2 2 1 3 1 2 2 1 1 1 3 2 2 3 3 3 2 3 2 1 3 3 1 1 3 3 2 3 3 2 3 1 1 3 3 1 1 3 2 2 1 3 3 3 1 2 3 2 1 3 2 3 3
 [286] 3 1 1 2 3 2 2 3 2 2 2 3 1 3 1 2 1 1 1 2 1 3 2 3 2 2 3 3 3 2 2 1 3 2 2 2 1 1 2 3 3 3 3 3 3 3 2 3 2 1 1 1 3 2 3 1 3
 [343] 1 2 2 1 3 2 2 3 2 2 1 2 2 2 1 1 3 1 2 2 2 2 3 2 2 1 3 3 1 1 1 3 3 2 3 3 2 2 3 3 2 2 2 2 2 2 2 1 1 2 3 1 2 2 3 1 3
 [400] 2 2 2 2 1 3 2 2 3 3 1 2 1 3 3 2 2 2 2 1 2 2 2 3 2 2 3 2 2 3 3 3 3 1 1 2 2 3 3 2 2 3 2 3 2 3 2 2 2 1 3 3 1 2 2 2 2
 [457] 2 3 1 3 2 1 1 3 3 3 2 3 2 2 3 1 3 1 2 1 3 3 2 1 1 1 3 2 1 1 2 3 3 3 1 3 2 2 3 3 1 2 3 2 3 2 2 1 2 3 3 3 2 3 2 3 2
 [514] 1 3 1 2 2 2 2 3 3 1 3 1 2 2 2 2 2 2 2 1 2 1 2 3 2 3 2 3 1 2 3 2 2 2 3 2 2 3 1 2 3 3 2 1 2 1 3 1 2 3 2 3 3 3 3 2 2
 [571] 2 1 2 2 2 1 1 1 1 3 2 1 2 1 1 1 3 3 1 1 3 2 2 1 2 3 2 3 1 2 3 1 3 1 3 3 1 3 1 2 1 1 3 3 1 1 2 3 1 3 1 3 1 3 3 1 2
 [628] 3 3 2 3 2 3 3 3 1 3 2 3 3 3 1 1 1 3 3 3 2 3 1 1 2 1 3 3 3 1 3 1 3 2 3 2 2 1 3 3 2 3 3 1 3 1 2 3 1 3 1 3 1 3 2 3 1
 [685] 3 2 2 3 3 1 3 1 2 1 3 2 1 3 1 3 3 3 1 2 3 1 3 1 2 3 3 1 1 1 1 2 2 1 3 1 3 1 3 2 1 3 1 2 2 2 3 3 2 1 3 3 3 3 3 2 2
 [742] 1 3 3 1 1 2 1 2 1 3 3 2 1 1 3 2 3 2 2 3 3 3 1 3 1 2 2 1 2 1 1 1 3 2 1 1 1 2 3 1 3 2 2 2 2 1 1 3 1 3 3 3 3 3 3 3 3
 [799] 2 1 1 3 1 2 1 1 2 2 1 3 2 1 1 3 3 3 2 2 1 1 3 1 1 3 2 1 3 1 3 2 2 3 1 3 3 3 2 2 2 3 3 3 1 1 1 1 3 1 1 3 2 2 1 1 3
 [856] 2 1 3 2 3 3 2 1 3 2 1 1 3 1 1 1 3 2 1 2 2 3 3 2 3 1 1 3 1 3 3 2 2 2 2 1 3 1 1 2 1 1 3 2 2 2 1 3 1 2 3 2 1 2 3 3 1
 [913] 1 1 1 2 2 1 2 1 3 1 2 3 1 2 1 1 2 3 2 1 2 2 3 3 3 2 3 2 2 3 2 3 3 1 2 2 2 2 2 1 1 3 3 2 1 1 2 1 1 1 1 3 1 1 1 3 2
 [970] 2 3 1 3 1 3 1 1 1 3 1 2 2 2 1 2 1 2 1 1 2 2 1 2 3 1 2 3 3 2 1
 [ reached getOption("max.print") -- omitted 750 entries ]

Within cluster sum of squares by cluster:
[1] 4164.678 4700.218 4580.780
 (between_SS / total_SS =  14.6 %)

Available components:

[1] "cluster"      "centers"      "totss"        "withinss"     "tot.withinss" "betweenss"    "size"        
[8] "iter"         "ifault"      

visualize clustering

# visualize clustering (3 clusters)

fviz_cluster(kmeans.result, data = data_for_cluster)

hiercrchical clustering

# draw a sample of 50 records from the data, so that the clustering plot will not be over crowded and easy to undrestand 

idx2<-sample(1:dim(data_for_cluster)[1], 50)
sample_c2<-data_for_cluster[idx2, ]

## hiercrchical clustering
hc2.cut<- hcut(sample_c2, k = 3, hc_method= "complete")

Visualize dendrogram

dendrogram is a tree diagram that displays the arrangement of data points in a hierarchical order based on their similarity or dissimilarity.

fviz_dend(hc2.cut,rect= TRUE)

# Visualize cluster
fviz_cluster(hc2.cut, ellipse.type= "convex")

average silhouette

This method calculates the average silhouette width for different values of k, determining how well data points fit into their assigned clusters.

 #average silhouette for each clusters 

avg_sil <- silhouette(kmeans.result$cluster,dist(data_for_cluster)) #a dissimilarity object inheriting from class dist or coercible to one. If not specified, dmatrix must be.
fviz_silhouette(avg_sil)#k-means clustering with estimating k and initializations

BCubed precision and recall

BCubed precision and recall are metrics used to evaluate the performance of clustering algorithms, particularly in the context of evaluating the quality of clustering assignments for individual data points.


cluster_assignments <- c(kmeans.result$cluster)
ground_truth_labels <- c(water_potability)
data <- data.frame(cluster = cluster_assignments, label = ground_truth_labels)

# Function to calculate BCubed precision and recall
calculate_bcubed_metrics <- function(data) {
  n <- nrow(data)
  precision_sum <- 0
  recall_sum <- 0

  for (i in 1:n) {
    cluster <- data$cluster[i]
    label <- data$label[i]
    
# Count the number of items from the same category within the same cluster
same_category_same_cluster <- sum(data$label[data$cluster == cluster] == label)
    
# Count the total number of items in the same cluster
total_same_cluster <- sum(data$cluster == cluster)
    
# Count the total number of items with the same category
total_same_category <- sum(data$label == label)
    
# Calculate precision and recall for the current item and add them to the sums
precision_sum <- precision_sum + same_category_same_cluster /total_same_cluster
recall_sum <- recall_sum + same_category_same_cluster / total_same_category
  }

  # Calculate average precision and recall
  precision <- precision_sum / n
  recall <- recall_sum / n

  return(list(precision = precision, recall = recall))
}

# Calculate BCubed precision and recall
metrics <- calculate_bcubed_metrics(data)

# Extract precision and recall from the metrics
precision <- metrics$precision
recall <- metrics$recall

# Print the results
cat("BCubed Precision:", precision, "\n")
BCubed Precision: 0.005399565 
cat("BCubed Recall:", recall, "\n")
BCubed Recall: 0.9334336 

Clustring3

K-means

# 3- run k-means clustering to find 4 clusters
#set a seed for random number generation  to make the results reproducible
set.seed(8953)
kmeans.result <- kmeans(data_for_cluster,4)
# print the clustering result
kmeans.result
K-means clustering with 4 clusters of sizes 455, 454, 473, 368

Cluster means:
          ph   Hardness     Solids Chloramines    Sulfate Conductivity Organic_carbon Trihalomethanes   Turbidity
1 -0.2146827 -0.7214547 -0.3677362   0.2968260  0.7101276  -0.46685877    -0.13233662       0.2631821 -0.22443204
2  0.5278807  0.5322546 -0.2851709  -0.2861510 -0.1194541  -0.47811425     0.49623590      -0.5686409  0.01320375
3 -0.4902566 -0.2272040  0.9167746  -0.1139594 -0.6508868   0.06680126    -0.01034781       0.1811282  0.26851135
4  0.2443319  0.5274071 -0.3718664   0.1324987  0.1059608   1.08121634    -0.43528104       0.1433192 -0.08392336

Clustering vector:
   [1] 1 2 1 2 2 3 3 3 4 3 1 3 3 1 2 3 3 2 1 2 2 2 2 3 2 2 4 3 3 2 4 3 3 3 3 4 4 4 3 4 2 4 4 4 3 3 3 1 3 2 2 4 1 2 4 2 1
  [58] 2 2 3 2 4 1 2 3 3 2 2 3 1 1 2 4 4 2 4 2 1 1 3 3 4 1 2 4 1 1 2 1 3 4 3 4 3 3 3 4 2 3 1 1 2 3 2 2 3 2 4 2 2 2 1 3 3
 [115] 2 2 3 4 2 2 4 2 3 3 2 3 1 4 2 4 2 2 4 4 4 1 2 4 2 4 3 1 1 4 1 3 3 3 2 4 1 3 3 3 3 4 4 4 1 3 3 1 4 2 3 3 1 2 2 3 1
 [172] 4 4 1 4 4 4 1 2 4 4 3 4 1 1 4 3 3 1 3 4 4 3 1 1 4 1 2 2 4 4 3 2 2 2 2 4 2 3 4 4 3 4 3 2 4 4 1 3 3 2 1 4 2 2 2 4 3
 [229] 1 4 2 2 4 2 1 3 1 1 4 1 2 1 3 2 2 3 2 3 4 3 1 2 3 3 4 1 3 3 2 3 2 2 4 1 4 3 3 3 1 3 2 4 1 4 3 3 2 4 3 2 2 3 2 4 3
 [286] 1 2 1 1 1 4 2 3 4 1 4 3 1 3 1 4 1 1 1 4 1 3 2 3 1 2 2 2 4 2 4 4 3 1 1 4 4 1 2 3 3 3 3 3 3 3 2 3 1 1 4 1 1 2 3 4 2
 [343] 1 4 4 1 2 4 1 3 4 2 3 2 4 2 3 1 3 1 4 2 2 3 3 2 1 1 3 3 1 1 3 3 3 2 3 3 2 2 2 3 2 2 4 4 2 2 2 1 1 4 4 1 1 2 2 1 4
 [400] 2 2 4 2 1 3 2 2 2 2 4 4 3 3 3 4 2 4 4 1 2 3 2 3 4 2 2 2 4 3 3 1 3 1 1 2 4 3 3 4 4 4 4 3 1 3 2 4 4 3 3 3 2 2 2 4 4
 [457] 4 2 2 3 2 1 1 3 3 3 4 3 4 4 3 4 3 1 2 1 3 3 2 1 2 1 3 2 1 1 2 4 4 3 2 1 2 2 2 3 1 2 3 2 3 2 4 1 4 4 3 3 4 3 2 3 4
 [514] 1 3 1 2 4 2 2 3 4 1 3 1 1 4 2 2 2 2 2 1 4 1 4 2 2 3 2 3 2 4 3 2 4 4 3 4 3 4 1 4 3 3 2 1 1 1 3 1 2 1 1 4 3 3 2 4 2
 [571] 4 1 4 4 4 4 2 1 1 2 4 1 4 2 1 1 3 4 1 4 1 4 4 4 4 3 4 3 4 2 2 2 3 1 3 3 2 3 1 3 1 1 3 3 1 1 4 3 4 3 1 3 4 3 3 1 1
 [628] 3 2 4 3 2 3 3 3 2 3 4 3 3 3 4 1 2 2 3 3 2 2 1 4 2 3 3 3 3 1 2 2 3 4 3 4 1 4 2 3 4 3 3 4 2 4 2 1 1 3 1 2 1 4 1 3 1
 [685] 3 2 4 4 3 4 3 1 2 1 3 1 1 3 1 3 3 4 3 4 3 1 3 1 2 3 3 2 1 1 4 4 4 2 3 1 2 1 2 4 1 1 2 4 4 1 4 2 2 2 4 3 3 2 2 2 4
 [742] 2 3 2 2 1 2 1 1 1 2 3 4 1 4 3 2 3 4 2 3 2 3 1 2 2 1 4 1 4 2 1 1 2 2 1 1 1 2 3 1 3 2 4 4 2 1 1 3 4 4 3 3 3 2 3 3 3
 [799] 4 4 1 3 1 4 1 2 4 2 1 3 3 2 1 3 3 1 2 4 1 1 3 1 1 3 4 1 2 1 3 2 4 3 1 3 3 3 2 4 4 3 3 3 1 2 1 1 3 2 1 3 4 2 2 1 3
 [856] 4 1 2 2 3 3 4 4 3 4 1 1 3 1 1 1 2 4 4 1 4 3 3 4 3 1 1 2 1 3 2 4 2 4 4 1 4 1 1 2 1 1 2 1 4 4 1 3 1 2 2 2 1 4 3 3 1
 [913] 1 3 1 3 2 1 4 1 2 1 4 3 4 2 1 4 1 1 2 1 2 4 3 3 3 2 3 4 2 3 2 3 3 1 4 2 4 4 2 1 1 2 3 2 4 1 4 3 3 1 1 3 1 1 1 2 4
 [970] 4 2 4 3 2 2 3 1 3 2 1 4 2 4 1 4 1 2 1 1 4 2 1 4 3 1 4 3 4 2 1
 [ reached getOption("max.print") -- omitted 750 entries ]

Within cluster sum of squares by cluster:
[1] 3278.341 3196.457 3576.576 2751.181
 (between_SS / total_SS =  18.7 %)

Available components:

[1] "cluster"      "centers"      "totss"        "withinss"     "tot.withinss" "betweenss"    "size"        
[8] "iter"         "ifault"      

visualize clustering

# visualize clustering (4 clusters)

fviz_cluster(kmeans.result, data = data_for_cluster)

hiercrchical clustering

# draw a sample of 50 records from the data, so that the clustering plot will not be over crowded and easy to undrestand 
idx3<-sample(1:dim(data_for_cluster)[1], 50)
sample_c3<-data_for_cluster[idx3, ]

## hiercrchicalclustering
hc3.cut<- hcut(sample_c3, k = 4, hc_method= "complete")

dendrogram

dendrogram is a tree diagram that displays the arrangement of data points in a hierarchical order based on their similarity or dissimilarity.

# Visualize dendrogram
fviz_dend(hc3.cut,rect= TRUE)

# Visualize cluster
fviz_cluster(hc3.cut, ellipse.type= "convex")

average silhouette

This method calculates the average silhouette width for different values of k, determining how well data points fit into their assigned clusters.

 #average silhouette for each clusters 

avg_sil <- silhouette(kmeans.result$cluster,dist(data_for_cluster)) #a dissimilarity object inheriting from class dist or coercible to one. If not specified, dmatrix must be.
fviz_silhouette(avg_sil)#k-means clustering with estimating k and initializations

BCubed precision and recall

BCubed precision and recall are metrics used to evaluate the performance of clustering algorithms, particularly in the context of evaluating the quality of clustering assignments for individual data points.


cluster_assignments <- c(kmeans.result$cluster)
ground_truth_labels <- c(water_potability)
data <- data.frame(cluster = cluster_assignments, label = ground_truth_labels)

# Function to calculate BCubed precision and recall
calculate_bcubed_metrics <- function(data) {
  n <- nrow(data)
  precision_sum <- 0
  recall_sum <- 0

  for (i in 1:n) {
    cluster <- data$cluster[i]
    label <- data$label[i]
    
# Count the number of items from the same category within the same cluster
same_category_same_cluster <- sum(data$label[data$cluster == cluster] == label)
    
# Count the total number of items in the same cluster
total_same_cluster <- sum(data$cluster == cluster)
    
# Count the total number of items with the same category
total_same_category <- sum(data$label == label)
    
# Calculate precision and recall for the current item and add them to the sums
precision_sum <- precision_sum + same_category_same_cluster /total_same_cluster
recall_sum <- recall_sum + same_category_same_cluster / total_same_category
  }

  # Calculate average precision and recall
  precision <- precision_sum / n
  recall <- recall_sum / n

  return(list(precision = precision, recall = recall))
}

# Calculate BCubed precision and recall
metrics <- calculate_bcubed_metrics(data)

# Extract precision and recall from the metrics
precision <- metrics$precision
recall <- metrics$recall

# Print the results
cat("BCubed Precision:", precision, "\n")
BCubed Precision: 0.005452594 
cat("BCubed Recall:", recall, "\n")
BCubed Recall: 0.9252644 

Clustring4

K-means run k-means clustering to find 5 clusters

#set a seed for random number generation  to make the results reproducible
set.seed(8953)
kmeans.result <- kmeans(data_for_cluster,5)
# print the clusterng result
kmeans.result
K-means clustering with 5 clusters of sizes 312, 363, 383, 322, 370

Cluster means:
          ph   Hardness     Solids Chloramines     Sulfate Conductivity Organic_carbon Trihalomethanes   Turbidity
1 -0.2402063 -0.8869290 -0.4290398  0.45724983  1.02228899  -0.14848187    -0.22705797     -0.05503729 -0.06200938
2  0.5144893  0.5465975 -0.2151085 -0.41557709  0.06315779   0.04059606     0.02107087     -0.98799721  0.41421355
3 -0.6240078 -0.2217340  1.0431533  0.07754613 -0.51231391  -0.02639079    -0.24179836      0.02394081  0.39912942
4  0.3629030  0.1293341 -0.3484486 -0.35866061 -0.20275280   0.81483681    -0.50711780      0.71413603 -0.44505488
5  0.0279054  0.3286095 -0.2037364  0.25400294 -0.21723734  -0.59643191     0.86241639      0.36944187 -0.37992295

Clustering vector:
   [1] 5 2 3 5 2 3 5 3 4 3 1 3 3 2 2 3 3 2 3 2 4 4 2 4 2 2 2 3 3 2 4 3 3 3 4 1 4 4 4 3 2 2 4 4 2 3 3 4 3 2 5 2 5 2 4 5 5
  [58] 5 2 5 5 2 1 2 4 3 5 3 3 1 5 2 2 4 5 4 2 4 4 3 3 1 4 2 2 1 1 2 4 3 4 3 4 4 3 3 3 5 4 3 1 2 4 5 2 3 2 4 5 2 2 3 3 3
 [115] 4 2 3 4 2 2 4 4 3 3 5 5 1 4 5 4 5 2 4 5 4 1 5 4 5 5 3 5 5 2 4 3 3 3 2 4 4 3 5 3 3 4 2 4 1 5 3 1 4 2 5 3 5 5 2 3 1
 [172] 4 2 4 4 1 2 1 2 4 4 3 2 1 1 4 5 3 2 5 3 4 3 1 1 5 4 5 5 4 2 3 2 5 5 4 4 2 3 3 3 4 4 3 5 4 4 1 3 3 2 1 4 4 2 2 2 3
 [229] 3 4 5 5 2 2 4 5 3 5 4 1 2 1 5 4 2 3 2 3 4 2 1 2 4 3 4 5 5 5 5 3 2 4 4 1 4 3 3 4 4 3 2 4 3 1 3 2 2 4 3 2 5 3 2 3 3
 [286] 1 2 1 1 3 4 5 2 2 1 2 3 1 3 5 2 3 5 1 4 5 3 2 3 1 2 2 5 3 2 4 1 3 5 4 4 4 5 2 3 3 3 3 3 3 2 2 3 5 1 1 5 5 4 5 2 2
 [343] 1 4 4 5 5 5 4 5 4 2 3 5 4 2 3 1 5 3 4 5 5 4 3 2 5 5 5 3 5 3 3 3 5 5 5 3 5 5 2 3 2 5 4 4 2 5 5 1 1 4 2 1 4 2 2 1 2
 [400] 2 5 4 1 1 3 5 2 2 2 1 2 3 3 3 4 2 4 2 3 5 5 2 3 4 5 5 5 4 4 3 5 3 2 4 5 5 3 5 4 4 3 5 3 5 3 5 4 4 3 3 4 2 5 2 5 4
 [457] 4 2 2 3 2 1 1 3 3 4 4 3 4 4 3 4 3 3 2 1 3 3 2 5 2 1 3 2 1 5 4 4 5 4 2 3 5 5 5 3 4 2 3 2 3 5 4 1 4 3 4 4 5 3 4 5 4
 [514] 1 3 1 2 4 2 2 3 3 4 3 5 4 4 2 2 5 2 5 5 2 5 1 2 4 3 2 5 2 4 3 2 2 5 3 5 4 5 5 5 4 2 4 1 4 5 3 1 5 4 4 3 5 3 5 4 5
 [571] 2 1 4 2 4 3 2 5 1 2 4 1 4 5 5 1 5 4 4 1 3 4 2 1 4 3 4 3 4 5 5 1 3 4 4 3 2 4 1 4 1 3 4 5 1 1 2 4 1 3 4 3 1 3 3 5 5
 [628] 4 2 4 4 1 5 3 3 2 3 5 5 3 4 2 5 2 2 3 4 5 2 1 2 5 3 3 3 3 5 2 2 3 4 4 4 5 2 4 5 4 3 3 1 2 1 2 4 1 3 1 2 4 4 4 3 5
 [685] 3 2 4 3 3 4 3 1 5 5 5 4 1 4 1 3 3 4 3 4 3 5 3 1 5 3 5 2 1 1 1 4 4 2 3 1 2 1 5 2 1 4 5 2 1 4 3 2 5 5 4 3 5 5 2 2 4
 [742] 2 3 2 2 1 5 4 5 3 2 3 2 1 1 3 5 3 4 2 3 3 3 1 2 2 1 4 1 5 2 5 5 5 5 1 1 4 5 3 1 3 5 2 4 5 1 1 3 4 4 3 3 5 5 3 3 3
 [799] 4 2 1 3 1 4 1 2 4 5 1 4 5 5 1 3 3 5 5 4 1 1 5 1 3 3 5 1 5 1 3 2 4 3 1 3 4 3 2 4 5 3 5 3 1 2 1 1 4 1 1 3 1 5 5 1 3
 [856] 3 1 2 5 3 3 2 1 3 2 1 1 3 1 1 1 5 4 4 1 4 3 3 5 3 5 1 2 1 3 5 2 2 4 5 1 3 1 1 2 1 1 5 4 4 4 1 5 3 5 2 5 5 4 3 3 1
 [913] 1 2 1 4 2 5 4 5 2 1 4 4 4 5 1 4 5 3 5 3 5 4 2 3 2 2 3 4 4 3 5 3 3 1 2 2 2 2 5 5 1 2 5 2 4 1 4 3 4 1 4 3 1 4 1 5 2
 [970] 4 5 1 3 2 2 3 4 2 5 5 2 5 5 1 2 1 5 1 4 1 2 1 2 3 5 5 3 2 5 1
 [ reached getOption("max.print") -- omitted 750 entries ]

Within cluster sum of squares by cluster:
[1] 2194.062 2488.613 2783.115 2372.250 2417.582
 (between_SS / total_SS =  22.1 %)

Available components:

[1] "cluster"      "centers"      "totss"        "withinss"     "tot.withinss" "betweenss"    "size"        
[8] "iter"         "ifault"      

visualize clustering

# visualize clustering (5 clusters)

fviz_cluster(kmeans.result, data = data_for_cluster)

hiercrchical clustering

# draw a sample of 50 records from the data, so that the clustering plot will not be over crowded and easy to undrestand 
idx4<-sample(1:dim(data_for_cluster)[1], 50)
sample_c4<-data_for_cluster[idx4, ]

## hiercrchicalclustering
hc4.cut<- hcut(sample_c4, k = 5, hc_method= "complete")

dendrogram

dendrogram is a tree diagram that displays the arrangement of data points in a hierarchical order based on their similarity or dissimilarity.

# Visualize dendrogram
fviz_dend(hc4.cut,rect= TRUE)

# Visualize cluster
fviz_cluster(hc4.cut, ellipse.type= "convex")

average silhouette

This method calculates the average silhouette width for different values of k, determining how well data points fit into their assigned clusters. determining how well data points fit into their assigned clusters.

 #average silhouette for each clusters 

avg_sil <- silhouette(kmeans.result$cluster,dist(data_for_cluster)) #a dissimilarity object inheriting from class dist or coercible to one. If not specified, dmatrix must be.
fviz_silhouette(avg_sil)#k-means clustering with estimating k and initializations

BCubed precision and recall

BCubed precision and recall are metrics used to evaluate the performance of clustering algorithms, particularly in the context of evaluating the quality of clustering assignments for individual data points.


cluster_assignments <- c(kmeans.result$cluster)
ground_truth_labels <- c(water_potability)
data <- data.frame(cluster = cluster_assignments, label = ground_truth_labels)

# Function to calculate BCubed precision and recall
calculate_bcubed_metrics <- function(data) {
  n <- nrow(data)
  precision_sum <- 0
  recall_sum <- 0

  for (i in 1:n) {
    cluster <- data$cluster[i]
    label <- data$label[i]
    
# Count the number of items from the same category within the same cluster
same_category_same_cluster <- sum(data$label[data$cluster == cluster] == label)
    
# Count the total number of items in the same cluster
total_same_cluster <- sum(data$cluster == cluster)
    
# Count the total number of items with the same category
total_same_category <- sum(data$label == label)
    
# Calculate precision and recall for the current item and add them to the sums
precision_sum <- precision_sum + same_category_same_cluster /total_same_cluster
recall_sum <- recall_sum + same_category_same_cluster / total_same_category
  }

  # Calculate average precision and recall
  precision <- precision_sum / n
  recall <- recall_sum / n

  return(list(precision = precision, recall = recall))
}

# Calculate BCubed precision and recall
metrics <- calculate_bcubed_metrics(data)

# Extract precision and recall from the metrics
precision <- metrics$precision
recall <- metrics$recall

# Print the results
cat("BCubed Precision:", precision, "\n")
BCubed Precision: 0.005507547 
cat("BCubed Recall:", recall, "\n")
BCubed Recall: 0.9201751 

Elbow method

elbow method helps find the optimal number of clusters (k) in k-means clustering. the “elbow” point is where the rate of decrease in WSS slows, indicating a good balance between cluster count and cluster compactness. The goal is to select the smallest k that retains most of the data’s variability.

# 3- Elbow method
#fviz_nbclust() with within cluster sums of squares (wss) method 
 
fviz_nbclust(data_for_cluster, kmeans, method = "wss") +
  geom_vline(xintercept = 5, linetype = 2)+
  labs(subtitle = "Elbow method")

# 2- silhouette method
#install.packages("NbClust")
library(NbClust)
#a)fviz_nbclust() with silhouette method using library(factoextra) 
fviz_nbclust(data_for_cluster, kmeans, method = "silhouette")+
  labs(subtitle = "Silhouette method")


fres.nbclust <- NbClust(data_for_cluster, distance="euclidean", min.nc = 2, max.nc = 10, method="kmeans", index="all")
*** : The Hubert index is a graphical method of determining the number of clusters.
                In the plot of Hubert index, we seek a significant knee that corresponds to a 
                significant increase of the value of the measure i.e the significant peak in Hubert
                index second differences plot. 
 

*** : The D index is a graphical method of determining the number of clusters. 
                In the plot of D index, we seek a significant knee (the significant peak in Dindex
                second differences plot) that corresponds to a significant increase of the value of
                the measure. 
 
******************************************************************* 
* Among all indices:                                                
* 7 proposed 2 as the best number of clusters 
* 6 proposed 3 as the best number of clusters 
* 1 proposed 4 as the best number of clusters 
* 2 proposed 5 as the best number of clusters 
* 2 proposed 6 as the best number of clusters 
* 1 proposed 7 as the best number of clusters 
* 1 proposed 8 as the best number of clusters 
* 1 proposed 9 as the best number of clusters 
* 2 proposed 10 as the best number of clusters 

                   ***** Conclusion *****                            
 
* According to the majority rule, the best number of clusters is  2 
 
 
******************************************************************* 

Total Within-Cluster Sum of Squares for k

WSS is to give you an indication of how well the data can be represented by a certain number of clusters. In k-means clustering, typically choose the number of clusters (k) that minimizes this total WSS.


for (k in 2:5) {
  kmeans_result <- kmeans(water_potability, centers = k)
  total_withinss <- kmeans_result$tot.withinss
  cat("Total Within-Cluster Sum of Squares for k =", k, ":", total_withinss, "\n")
}
Total Within-Cluster Sum of Squares for k = 2 : 35783887082 
Total Within-Cluster Sum of Squares for k = 3 : 18190822072 
Total Within-Cluster Sum of Squares for k = 4 : 10763774244 
Total Within-Cluster Sum of Squares for k = 5 : 7447599638 

Comparison Criteria:

Clustring1 Clustring2 Clustring3 Clustring4
average silhouette width 0.09 0.08 0.08 0.08
total within-cluster sum of square 35783784875 18188054859 10763906537 7332617467
BCubed Precision 0.005341313 0.005399565 0.005452594 0.005507547
BCubed Recall 0.9500965 0.9334336 0.9252644 0.9201751

After testing and using all The selection of k=5 is well-founded based on a comprehensive analysis of clustering metrics. The Elbow method, a widely recognized technique, distinctly highlights k=5 as the optimal number, demonstrating a significant reduction in within-cluster variance. Beyond the Elbow method, other crucial metrics reinforce this choice. The average silhouette width, a measure of cluster cohesion and separation, is highest at 0.09 for k=5, indicating well-defined clusters. BCubed Precision (0.0053507) and Recall (0.9501209) consistently favor k=5, attesting to the accuracy and completeness of the clusters. Furthermore, the Total Within-Cluster Sum of Squares for k=5 (7263150876) is notably lower, signifying compact and distinct clusters. This convergence of evidence from various metrics provides a robust justification for k=5, ensuring that the resulting clusters are both statistically sound and meaningful in capturing the underlying structure of the dataset.

A classification approach is more fitting for the task of determining water potability. The inherent design of classification models to make binary decisions aligns seamlessly with the goal of identifying whether water is safe for consumption. This focused predictive capability provides actionable insights crucial for effective water treatment decisions. The classification model directly communicates the safety status of a water sample, aiding in adherence to quality standards. While clustering serves well in exploratory analysis, it might not be as directly aligned with the precise objective of predicting water potability. Hence, for this specific task, a binary classification model is recommended.

Evaluation and Comparison

Mining task Comparison Criteria
Classification

We experimented with different dataset splitting sizes to create the decision tree, and for each size, we used four classification algorithms:

  • Information gain (ID3):

    • 90 % training set and 10% testing set:

    • 80 % training set and 20% testing set:

    • 70 % training set and 30% testing set:

  • Gain ratio (C4.5):

    • K-folds = 3:

    • K-folds = 5:

    • K-folds = 10:

      Since the tree was enormous and to make it more easily accessible, we’ve uploaded it as a PDF file file on Google Drive. This way, it can be viewed and analyzed more efficiently.

      Number of Leaves : 437

      Size of the tree : 873

  • Gain ratio (C5.0):

    • 90 % training set and 10% testing set:

    • 80 % training set and 20% testing set:

    • 70 % training set and 30% testing set:

  • Gini index (CART):

    • 90 % training set and 10% testing set:

    • 80 % training set and 20% testing set:

    • 70 % training set and 30% testing set:

Clustering

During our experimentation, we tested with five different numbers of K clusters:

  • K = 2:

    • Clustering visualization:

    • Clustering sample visualization:

    • Dendrogram:

    • Each cluster Silhouette width and size:

    • Average Silhouette width:

  • K = 3:

    • Clustering visualization:

    • Clustering sample visualization:

    • Dendrogram:

    • Each cluster Silhouette width and size:

    • Average Silhouette width:

  • K = 4:

    • Clustering visualization:

    • Clustering sample visualization:

    • Dendrogram:

    • Each cluster Silhouette width and size:

    • Average Silhouette width:

  • K = 5:

    • Clustering visualization:

    • Clustering sample visualization:

    • Dendrogram:

    • Each cluster Silhouette width and size:

    • Average Silhouette width:

  • Optimal number of clusters:

    • Silhouette method:

    • Based on majority rule:

    • Elbow method:

Findings

In the beginning, we selected a dataset that represents the water data to predict the probability of determining whether water is safe for consumption to give people the proper measures to help with water treatment decisions and ensure compliance with quality standards. To have efficient, correct, and the best possible accuracy results, we applied several preprocessing techniques that improved the efficiency of the data.

We used several plotting methods, such as boxplots, scatter, histograms, and bar plots, to illustrate the data to help us understand our data and make the appropriate preprocessing techniques. Based on the blots and other commands, we removed all null, missing, and outlier values that can negatively affect the results.

Also, we applied data transformation, so we normalized and discretized some attributes to give them equal weight and to facilitate handling the data during data mining tasks. We check attribute correlation to find redundant data. Thus, we applied the data mining tasks: Classification and Clustering.

For classification, we use the decision tree method to construct our model. We tried four algorithms with three different sizes each of training and testing data to get the best result for construction and evaluation, and we concluded the following results:

The model with the best accuracy was the Gain ratio algorithm with 10 K-fold, meaning that most tuples were correctly classified.

The tree’s root is the Sulfate attribute, which has the maximum entropy that splits the data into a binary sub-tree where the first node for tuples was Sulfate <= [396,440), and the second was Sulfate > [396,440). The number of leaves was 437, and the tree size was 873.

From the plot of the tree, we concluded the following results:

As indicated by the evaluation metrics, the model’s performance demonstrates a high level of accuracy of 92.23%, precision of 91.67%, sensitivity of 95.97%, and specificity of 86.40%. The accuracy metric reflects the overall correctness of the model’s predictions across both positive and negative instances. A precision of 91.67% signifies the reliability of the model when predicting positive instances, indicating that the vast majority of positive predictions are accurate. The high sensitivity of 95.97% means the model’s effectiveness in correctly identifying a substantial proportion of positive instances is crucial in scenarios where capturing positives is a priority. Additionally, the specificity of 86.40% suggests that the model is adept at correctly identifying negative samples. These results collectively suggest a well-balanced model with strong predictive capabilities across different aspects of the classification task.

Also, the tree illustrates that all attributes (Hardness, Solids, Chloramines, Conductivity, Organic carbon, Trihalomethanes, and Turbidity) were involved in predicting the class label.

According to the model, water can be considered potable if particular criteria are met. For example When:

  • The sulfate concentration falls below the range of [396, 440)

  • The trihalomethane concentration is in the range [90, 100). 

  • The pH level is within [7, 11). 

  • The chloramine concentration falls within the range [7, 11).

These intervals represent the thresholds or conditions established by the decision tree, and when water samples meet these criteria, the model predicts that the water is potable.

This level of detail provides valuable insights into the factors contributing to water potability according to the decision tree. It also offers a practical guideline for assessing water potability based on the specified intervals for Sulfate, trihalomethanes, pH, and chloramine concentrations. Users and stakeholders can use this information to make informed decisions about the quality of water samples, utilizing the decision tree’s identified conditions as a tool for evaluating water portability.

For Clustering, we used the K-means algorithm with four different Ks to find the optimal number of clusters. We calculated the average silhouette width for each cluster and other metrics, and we concluded the following results:

The model with the optimal number of clusters is K = 2 since it has the best average silhouette width, meaning that objects within the same cluster are close to each other and, as far as possible, to the objects in the other cluster.

However, according to WSS (Total Within-Cluster Sum of Squares), the model with the optimal number of clusters is K = 5 since it has a minimal WSS.

After conducting tests and analysis, we found that our dataset’s optimal number of clusters is K=5. We used the Elbow method and other metrics such as silhouette width score of 0.8, BCubed precision of 0.005507547, recall score of 0.9201751, and Total Within-Cluster Sum of Squares 7332617467 to support our conclusion.

Finally, both models help predict whether the water is potable and allow us to reach our goal, assisting people to take precautions if they threaten to get positioned. However, since our data contains a class label “Potability,” this makes supervised learning models Classification more accurate and suitable to apply than unsupervised learning models Clustering, as the expected output is known beforehand. This way, we make use of the class label attribute.

References

[1] “Water Quality and Potability,” Kaggle, Sep. 04, 2023. https://www.kaggle.com/datasets/uom190346a/water-quality-and-potability

[2] J. Brownlee, “Non-Linear Classification in R with Decision Trees,” MachineLearningMastery.com, Aug. 22, 2019. https://machinelearningmastery.com/non-linear-classification-in-r-with-decision-trees/

[3] “RPubs - Classification and Regression Trees (CART) in R.” https://rpubs.com/camguild/803096

[4] “RPubs - Data Mining: Classification with Decision Trees.” https://rpubs.com/kjmazidi/195428

[5] Prabhudev Konana, “Classification using RStudio,” YouTube, Apr. 11, 2016. https://www.youtube.com/watch?v=ImbXdYrT59s

[6]J. Brownlee, “Feature Selection with the Caret R Package,” MachineLearningMastery.com, Aug. 22, 2019. https://machinelearningmastery.com/feature-selection-with-the-caret-r-package/

LS0tCnRpdGxlOiAiV2F0ZXIgUXVhbGl0eSBhbmQgUG90YWJpbGl0eSIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKIyMgVGhpcyBjb2RlIGlzIHJ1bm5pbmcgdXNpbmcgUiBub3RlYm9vayBpbiBSU3R1ZGlvCgojIyMgVGhlIFByb2JsZW0KCldhdGVyIGlzIHZlcnkgaW1wb3J0YW50IHRvIHRoZSBjb250aW51aXR5IG9mIGxpZmUgYW5kIGlzIG9uZSBvZiB0aGUgc2l4IGVzc2VudGlhbCBudXRyaWVudHMgKGNhcmJvaHlkcmF0ZXMsIHByb3RlaW4sIGZhdCwgdml0YW1pbnMsIGFuZCBtaW5lcmFscykuIEFwcHJveGltYXRlbHkgNzAlIG9mIHRoZSBwbGFudHMgYXJlIGNvdmVyZWQgd2l0aCB3YXRlciwgYnV0IG9ubHkgMi41JSBhcmUgc3VpdGFibGUgZm9yIGRyaW5raW5nIG9yIGN1bHRpdmF0aW9uLiBBcyBodW1hbnMgdXNlIG1vcmUgd2F0ZXIsIGl0J3MgZ2V0dGluZyBoYXJkZXIgdG8gZmluZCB3YXRlciBmb3IgY29uc3VtcHRpb24sIHdoZXRoZXIgaXQncyBiZWNhdXNlIG9mIGZlcnRpbGl6ZXJzLCBpbmR1c3RyaWFsIHBvbGx1dGlvbiwgb3IgZXhjZXNzaXZlIHVzYWdlIG9mIHdhdGVyLCB3aGljaCBjYXVzZXMgdGhlIGdyb3VuZHdhdGVyIHJlc2Vydm9pcnMgaW4gZGVuc2VseSBwb3B1bGF0ZWQgY2l0aWVzIHRvIHNocmluay4gQW5kIHdpdGggaW5jcmVhc2luZyBwb3B1bGF0aW9uIGRlbnNpdHksIHdlIG5lZWQgbW9yZSB3YXRlciBhbmQgZm9vZCwgc28gb25lIG9mIHRoZSBzb2x1dGlvbnMgaXMgd2F0ZXIgZGVzYWxpbmF0aW9uIHRvIG1ha2UgaXQgcG90YWJsZS4gSW4gb3JkZXIgdG8gYXNzZXNzIHF1YWxpdHkgUG90YWJpbGl0eSAsIHdoaWNoIGlzIHRoZSBzdWl0YWJpbGl0eSBvZiB3YXRlciBmb3IgaHVtYW4gY29uc3VtcHRpb24sIHdlIG5lZWQgcXVhbGl0eSBtZWFzdXJlbWVudHMgYW5kIGFzc2Vzc21lbnRzLgoKIyMjIEdvYWxzOgoKV2UgYXJlIGNvbGxlY3RpbmcgYSBkYXRhc2V0IG9uIHdhdGVyIHF1YWxpdHkgdG8gdHJhaW4gYSBtYWNoaW5lIGxlYXJuaW5nIG1vZGVsIGZvciBiaW5hcnkgY2xhc3NpZmljYXRpb246IGRldGVybWluaW5nIHdoZXRoZXIgd2F0ZXIgaXMgc2FmZSBmb3IgY29uc3VtcHRpb24gKDEpIG9yIG5vdCAoMCkuIFRoaXMgbW9kZWwgd2lsbCBoZWxwIHdpdGggd2F0ZXIgdHJlYXRtZW50IGRlY2lzaW9ucyBhbmQgZW5zdXJlIGNvbXBsaWFuY2Ugd2l0aCBxdWFsaXR5IHN0YW5kYXJkcy4gV2UgYXBwbGllZCBkaWZmZXJlbnQgU3VtbWFyeml0aW9uIGFuZCBwbG90dGluZyBtZXRob2RzIHRvIGhlbHAgdXMgdG8gdW5kZXJzdGFuZCBvdXIgZGF0YXNldCwgc3VjaCBhcyBzY2F0dGVyLCBoaXN0b2dyYW0gYW5kIGJhciBwbG90LiBUaGVuLCB3ZSBhcHBseWVkIHByZXByb2Nlc3MgaW4gb3VyIGRhdGEgdXNpbmcgZGF0YSBjbGVhbmluZywgZGF0YSB0cmFuc2Zvcm1hdGlvbiBhbmQgZmVhdHVyZSBzZWxlY3Rpb24uCgojIyMgQ2xhc3NpZmljYXRpb24gYW5kIENsdXN0ZXJpbmcgR29hbDoKCjEtY2xhc3NpZmljYXRpb24gaW4gdGhpcyBkYXRhc2V0IGlzIHRvIGJ1aWxkIGEgcHJlZGljdGl2ZSBtb2RlbCB0aGF0IGNhbiBjbGFzc2lmeSB3YXRlciBzYW1wbGVzIGludG8gdHdvIGNhdGVnb3JpZXM6IHBvdGFibGUgKHN1aXRhYmxlIGZvciBjb25zdW1wdGlvbikgb3Igbm9uLXBvdGFibGUgKG5vdCBzdWl0YWJsZSBmb3IgY29uc3VtcHRpb24pLgoKMi1jbHVzdGVyaW5nIGluIHRoaXMgZGF0YXNldCBpcyB0byBpZGVudGlmeSBuYXR1cmFsIGdyb3VwaW5ncyBvciBjbHVzdGVycyB3aXRoaW4gdGhlIHdhdGVyIHNhbXBsZXMgYmFzZWQgb24gdGhlaXIgcXVhbGl0eSBwYXJhbWV0ZXJzLgoKIyMjIERhdGEKCiMjIyMgU291cmNlIG9mIHRoZSBkYXRhc2V0OgoKS2FnZ2xlCgojIyMjIExpbmsgb2YgdGhlIGRhdGFzZXQ6CgpbV2F0ZXIgUXVhbGl0eSBhbmQgUG90YWJpbGl0eV0oaHR0cHM6Ly93d3cua2FnZ2xlLmNvbS9kYXRhc2V0cy91b20xOTAzNDZhL3dhdGVyLXF1YWxpdHktYW5kLXBvdGFiaWxpdHkpCgojIyMjIEluZm9ybWF0aW9uIGFib3V0IHRoZSBkYXRhc2V0CgppdCBpcyBjb250YWlucyAxMCBhdHRyaWJ1dGVzLCAzMjc2IG9iamVjdHMsIGFuZCB0aGUgY2xhc3MgbGFiZWwgZm9yIG91ciBkYXRhc2V0IGlzIFBvdGFiaWxpdHkuCgojIyMjIEF0dHJpYnV0ZSBpbmZvcm1hdGlvbgoKKy0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0rCnwgQXR0cmlidXRlICAgICAgIHwgRGVzY3JpcHRpb24gICAgICAgICAgICAgICAgICAgfCBEYXRhIFR5cGUgICAgfCBQb3NzaWJsZSBWYWx1ZXMgfAorPT09PT09PT09PT09PT09PT0rPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PSs9PT09PT09PT09PT09PSs9PT09PT09PT09PT09PT09PSsKfCBwaCAgICAgICAgICAgICAgfCBwSCBsZXZlbCBvZiB3YXRlciAgICAgICAgICAgICB8IGRlY2ltYWwgICAgICB8IDAtMTQgICAgICAgICAgICB8CistLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tKwp8IEhhcmRuZXNzICAgICAgICB8IFdhdGVyIGhhcmRuZXNzIGluIHdhdGVyICAgICAgIHwgZGVjaW1hbCAgICAgIHwgNDcuNC0zMjMgICAgICAgIHwKKy0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0rCnwgU29saWRzICAgICAgICAgIHwgRGlzc29sdmVkIHNvbGlkcyBpbiB3YXRlciAgICAgfCBkZWNpbWFsICAgICAgfCAzMjEtNjEuMmsgICAgICAgfAorLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLSsKfCBDaGxvcmFtaW5lcyAgICAgfCBDaGxvcmFtaW5lcyBjb25jZW50cmF0aW9uICAgICB8IGRlY2ltYWwgICAgICB8IDAuMzUtMTMuMSAgICAgICB8CistLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tKwp8IFN1bGZhdGUgICAgICAgICB8IFN1bGZhdGUgY29uY2VudHJhdGlvbiAgICAgICAgIHwgZGVjaW1hbCAgICAgIHwgMTI5LTQ4MSAgICAgICAgIHwKKy0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0rCnwgQ29uZHVjdGl2aXR5ICAgIHwgRWxlY3RyaWNhbCBjb25kdWN0aXZpdHkgICAgICAgfCBkZWNpbWFsICAgICAgfCAxODEtNzUzICAgICAgICAgfAorLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLSsKfCBPcmdhbmljX2NhcmJvbiAgfCBPcmdhbmljIGNhcmJvbiBjb250ZW50ICAgICAgICB8IGRlY2ltYWwgICAgICB8IDIuMi0yOC4zICAgICAgICB8CistLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tKwp8IFRyaWhhbG9tZXRoYW5lcyB8IFRyaWhhbG9tZXRoYW5lcyBjb25jZW50cmF0aW9uIHwgZGVjaW1hbCAgICAgIHwgMC43NC0xMjQgICAgICAgIHwKKy0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0rCnwgVHVyYmlkaXR5ICAgICAgIHwgVHVyYmlkaXR5IGxldmVsICAgICAgICAgICAgICAgfCBkZWNpbWFsICAgICAgfCAxLjQ1LTYuNzQgICAgICAgfAorLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLSsKfCBQb3RhYmlsaXR5ICAgICAgfCBJbmRpY2F0ZXMgd2F0ZXIgcG90YWJpbGl0eSAgICB8IGJvb2xlYW4gICAgICB8IDAtMSAgICAgICAgICAgICB8CistLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tKwoKIyBMaWJyYXJ5OgoKYGBge3J9CiNpbnN0YWxsLnBhY2thZ2VzKCJjYXJldCIpCiNpbnN0YWxsLnBhY2thZ2VzKCJnbG1uZXQiKQojaW5zdGFsbC5wYWNrYWdlcygiQm9ydXRhIikKI2luc3RhbGwucGFja2FnZXMoIm1sYmVuY2giKQojaW5zdGFsbC5wYWNrYWdlcygicmFuZG9tRm9yZXN0IikKbGlicmFyeShjbHVzdGVyKQpsaWJyYXJ5KGZhY3RvZXh0cmEpIApsaWJyYXJ5KG91dGxpZXJzKQpsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KG1sYmVuY2gpCmxpYnJhcnkoY2FyZXQpCmxpYnJhcnkoZ2xtbmV0KQpsaWJyYXJ5KEJvcnV0YSkKbGlicmFyeShnZ3Bsb3QyKQpsaWJyYXJ5KHJhbmRvbUZvcmVzdCkKbGlicmFyeShwUk9DKQpsaWJyYXJ5KGUxMDcxKQpsaWJyYXJ5KGNhcmV0KQpsaWJyYXJ5KHBhcnR5KQpsaWJyYXJ5KHBhcnR5a2l0KQpsaWJyYXJ5KFJXZWthKQpsaWJyYXJ5KEM1MCkKbGlicmFyeShwcmludHIpCmxpYnJhcnkocnBhcnQpCmxpYnJhcnkocnBhcnQucGxvdCkKCmdldHdkKCkKI3NldHdkKCIvVXNlcnMvbWFoYXlpZS9Eb2N1bWVudHMvR2l0SHViL0RNMVByb2plY3QiKQpgYGAKCmBgYHtyfQp3YXRlcl9wb3RhYmlsaXR5ID0gcmVhZC5jc3YoJ0RhdGFzZXQvd2F0ZXJfcG90YWJpbGl0eS5jc3YnKQoKc3RyKHdhdGVyX3BvdGFiaWxpdHkpCmBgYAoKIyMjIHNhbXBsZSBvZiBkYXRhCgpzYW1wbGUgb2YgcmF3IGRhdGFzZXQoZmlyc3QgMTAgcm93cyk6CgpgYGB7cn0KCmhlYWQod2F0ZXJfcG90YWJpbGl0eSwxMCkKYGBgCgpzYW1wbGUgb2YgcmF3IGRhdGFzZXQobGFzdCAxMCByb3dzKToKCmBgYHtyfQp0YWlsKHdhdGVyX3BvdGFiaWxpdHksIDEwKQpgYGAKCkZpdmUgbnVtYmVyIHN1bW1hcnkgb2YgZWFjaCBhdHRyaWJ1dGUgaW4gb3VyIGRhdGFzZXQ6CgpgYGB7cn0Kc3VtbWFyeSh3YXRlcl9wb3RhYmlsaXR5KQpgYGAKCiMjIyMgU2FtcGxlIG9mIFdhdGVyX3BvdGFiaWxpdHkgZGF0YXNldAoKVGhpcyBpcyBhIHNhbXBsZSBvZiB0aGUgZGF0YXNldCB0byBoZWxwIHRvIHVuZGVyc3RhbmQgaG93IGl0IGlzIHN0cnVjdHVyZWQgYW5kIG9yZ2FuaXplZAoKYGBge3J9CnNhbXBsZSh3YXRlcl9wb3RhYmlsaXR5KQpgYGAKCiMjIyBOdW1iZXIgb2YgY29sdW1uIGFuZCByb3dzCgpgYGB7cn0KZGltKHdhdGVyX3BvdGFiaWxpdHkpCmBgYAoKIyMjIENoZWNraW5nIGZvciBtaXNzaW5nIHZhbHVlczoKClRoZSBhYnNlbmNlIG9mIGRhdGEgaW4gY2VydGFpbiB2YXJpYWJsZXMgb3IgY29sdW1ucyBpbiBhIGRhdGFzZXQgaXMgcmVmZXJyZWQgdG8gYXMgbWlzc2luZyBvciBudWxsIHZhbHVlcyBkdWUgdG8gdmFyaW91cyByZWFzb25zLiBJdCBjYW4gaGF2ZSBhIG5lZ2F0aXZlIGltcGFjdCBvbiB0aGUgZGF0YXNldCdzIGVmZmljaWVuY3kgYW5kIHRoZSBpbmZvcm1hdGlvbiB0aGF0IGNhbiBiZSB0YWtlbiBmcm9tIGl0IGxhdGVyLCBzbyB3ZSBjaGVja2VkIHRvIHNlZSB3aGV0aGVyIG91ciBkYXRhIGhhZCBtaXNzaW5nIG9yIG51bGwgdmFsdWVzIGFuZCBlbGltaW5hdGVkIHRoZXNlIHJvd3MgdG8gcHJvZHVjZSBhIG1vcmUgZWZmaWNpZW50IGRhdGFzZXQuCgpmaXJzdCB3ZSBjaGVja2VkIGZvciBtaXNzaW5nIHZhbHVlIHRvIGVuc3VyZXMgYWNjdXJhdGUgc3RhdGlzdGljcywgcmVsaWFibGUgdmlzdWFsaXphdGlvbnMsIGFuZCBndWlkZXMgZGVjaXNpb25zIG9uIGltcHV0YXRpb24gb3IgcmVtb3ZhbCBvZiBtaXNzaW5nIGRhdGEuCgpgYGB7cn0KZGltKHdhdGVyX3BvdGFiaWxpdHkpCnN1bShpcy5uYSh3YXRlcl9wb3RhYmlsaXR5KSkKYGBgCgojIyMgUmVtb3ZlIHJvd3Mgd2l0aCBtaXNzaW5nIHZhbHVlcwoKYGBge3J9CmNvbFN1bXMoaXMubmEod2F0ZXJfcG90YWJpbGl0eSkpCndhdGVyX3BvdGFiaWxpdHkgPSBuYS5vbWl0KHdhdGVyX3BvdGFiaWxpdHkpCmBgYAoKIyMjIyBTZWNvbmQgcmVtb3ZlIE5BIHJvd3MKCmBgYHtyfQpjb2xTdW1zKGlzLm5hKHdhdGVyX3BvdGFiaWxpdHkpKQpgYGAKCiMjIyBTdGF0aXN0aWNhbCBNZWFzdXJlczoKCiMjIyBJbiB0aGUgZ2l2ZW4gY29kZSwgeW91J3ZlIHVzZWQgdGhlIHN1bW1hcnkgZnVuY3Rpb24gdG8gb2J0YWluIGtleSBzdGF0aXN0aWNhbCBtZWFzdXJlcyBmb3IgdmFyaWFibGVzIHN1Y2ggYXMgIkNvbmR1Y3Rpdml0eSwiICJPcmdhbmljX2NhcmJvbiwiICJIYXJkbmVzcywiIGV0Yy4sIGluIHRoZSB3YXRlcl9wb3RhYmlsaXR5IGRhdGFzZXQuIFRoZXNlIG1lYXN1cmVzIGluY2x1ZGUgbWluaW11bSwgMXN0IHF1YXJ0aWxlLCBtZWRpYW4sIG1lYW4sIDNyZCBxdWFydGlsZSwgYW5kIG1heGltdW0gdmFsdWVzLCBvZmZlcmluZyBhIHN1Y2NpbmN0IG92ZXJ2aWV3IG9mIGVhY2ggdmFyaWFibGUncyBkaXN0cmlidXRpb24gYW5kIGNoYXJhY3RlcmlzdGljcy4gVGhpcyBwcm92aWRlcyBlc3NlbnRpYWwgaW5zaWdodHMgZm9yIHRoZSBpbml0aWFsIGV4cGxvcmF0aW9uIGFuZCB1bmRlcnN0YW5kaW5nwqBvZsKgdGhlwqBkYXRhc2V0LgoKV2l0aCB1c2luZyBtaW5pbXVtLCBtYXhpbXVtLCBtZWFuLCBtZWRpYW4gbGF3cyBpdCBoZWxwcyB0byBwcm92aWRlIGFuIG92ZXJ2aWV3IG9mIHRoZSBkYXRhJ3Mga2V5IGNoYXJhY3RlcmlzdGljcwoKYGBge3J9CnN1bW1hcnkod2F0ZXJfcG90YWJpbGl0eSRDb25kdWN0aXZpdHkpCnN1bW1hcnkod2F0ZXJfcG90YWJpbGl0eSRPcmdhbmljX2NhcmJvbikKc3VtbWFyeSh3YXRlcl9wb3RhYmlsaXR5JEhhcmRuZXNzKQpzdW1tYXJ5KHdhdGVyX3BvdGFiaWxpdHkkU29saWRzKQpzdW1tYXJ5KHdhdGVyX3BvdGFiaWxpdHkkQ2hsb3JhbWluZXMpCnN1bW1hcnkod2F0ZXJfcG90YWJpbGl0eSRQb3RhYmlsaXR5KQpzdW1tYXJ5KHdhdGVyX3BvdGFiaWxpdHkkU3VsZmF0ZSkKc3VtbWFyeSh3YXRlcl9wb3RhYmlsaXR5JFRyaWhhbG9tZXRoYW5lcykKc3VtbWFyeSh3YXRlcl9wb3RhYmlsaXR5JFR1cmJpZGl0eSkKc3VtbWFyeSh3YXRlcl9wb3RhYmlsaXR5JHBoKQpgYGAKCiMjIERhdGEgUHJlcHJvY2Vzc2luZyA6CgojIyMgRGF0YSBUcmFuc2Zvcm1hdGlvbjoKClRoZSBwcm9jZXNzIG9mIGNvbnZlcnRpbmcgb3IgbW9kaWZ5aW5nIHJhdyBkYXRhIGludG8gYSBkaWZmZXJlbnQgZm9ybWF0IG9yIHN0cnVjdHVyZSB0byBtYWtlIGl0IG1vcmUgc3VpdGFibGUgZm9yIGFuYWx5c2lzIG9yIG1vZGVsaW5nCgpUaGlzIHN0ZXAgaW52b2x2ZWQgdHJhbnNmb3JtaW5nIHRoZSBjbGFzcyBsYWJlbCwgUG90YWJpbGl0eSwgaW50byBjYXRlZ29yaWNhbCBkYXRhLiBXZSBjaGFuZ2VkIHRoZSBudW1lcmljIGRhdGEgdG8gJ05vdCBQb3RhYmxlJyBhbmQgJ1BvdGFibGUnIHRvIGluZGljYXRlIHdoZXRoZXIgdGhlIHdhdGVyIGlzIHNhZmUgZm9yIGh1bWFuIGNvbnN1bXB0aW9uLCB3aGVyZSAxIHJlcHJlc2VudHMgJ1BvdGFibGUnLCBhbmQgMCByZXByZXNlbnRzICdOb3QgUG90YWJsZS4KCmBgYHtyfQp3YXRlcl9wb3RhYmlsaXR5JFBvdGFiaWxpdHlbd2F0ZXJfcG90YWJpbGl0eSRQb3RhYmlsaXR5ID09ICcwJ10gPC0gJ05vdCBQb3RhYmxlJwp3YXRlcl9wb3RhYmlsaXR5JFBvdGFiaWxpdHlbd2F0ZXJfcG90YWJpbGl0eSRQb3RhYmlsaXR5ID09ICcxJ10gPC0gJ1BvdGFibGUnCgp3YXRlcl9wb3RhYmlsaXR5JFBvdGFiaWxpdHkgPC0gYXMuZmFjdG9yKHdhdGVyX3BvdGFiaWxpdHkkUG90YWJpbGl0eSkKdGFibGUod2F0ZXJfcG90YWJpbGl0eSRQb3RhYmlsaXR5KQoKYGBgCgpgYGB7cn0KcHJpbnQod2F0ZXJfcG90YWJpbGl0eSkKYGBgCgp0aGUgUk9TRSBwYWNrYWdlIHRvIGFkZHJlc3MgY2xhc3MgaW1iYWxhbmNlIGluIGEgYmluYXJ5IGNsYXNzaWZpY2F0aW9uIHNjZW5hcmlvIHdpdGggYSAnUG90YWJpbGl0eScgdGFyZ2V0IHZhcmlhYmxlLiBUaGUgY29kZSBjb252ZXJ0cyAnUG90YWJpbGl0eScgdG8gYSBmYWN0b3IsIHBlcmZvcm1zIG92ZXJzYW1wbGluZyBvbiB0aGUgbWlub3JpdHkgY2xhc3MgdXNpbmcgdGhlIG92dW4uc2FtcGxlIGZ1bmN0aW9uLCBhbmQgZGlzcGxheXMgdGhlIGJhbGFuY2VkIGRhdGFzZXQgYWxvbmdzaWRlIHRoZSBvcmlnaW5hbCBmb3IgYSBjb21wYXJpc29uIG9mIGNsYXNzIGRpc3RyaWJ1dGlvbnMuIFRoaXMgcHJlcHJvY2Vzc2luZyBzdGVwIGVuaGFuY2VzIG1vZGVsIGdlbmVyYWxpemF0aW9uIGJ5IGVuc3VyaW5nIGJldHRlciByZXByZXNlbnRhdGlvbiBvZiB0aGUgbWlub3JpdHkgY2xhc3MgZHVyaW5nIHRyYWluaW5nLiBUaGUgb3ZlcnNhbXBsaW5nIGlzIGFwcGxpZWQgdG8gYWxsIGZlYXR1cmVzIGV4Y2VwdCB0aGUgdGFyZ2V0IHZhcmlhYmxlLgoKIyMjIE91dGxpZXJzOgoKVGhleSBhcmUgb2JzZXJ2YXRpb25zIHRoYXQgbGllIGZhciBhd2F5IGZyb20gdGhlIG1ham9yaXR5IG9mIHRoZSBkYXRhLiBPdXRsaWVycyBjYW4gb2NjdXIgZHVlIHRvIHZhcmlvdXMgcmVhc29ucyBzdWNoIGFzIG1lYXN1cmVtZW50IGVycm9ycywgZXhwZXJpbWVudGFsIGFub21hbGllcywgb3IgZ2VudWluZSBleHRyZW1lIHZhbHVlcy4KCiMjIyMgYmVmb3JlIHJlbW92aW5nIG91dGxpZXI6CgpgYGB7cn0KZGltKHdhdGVyX3BvdGFiaWxpdHkpCmhlYWQod2F0ZXJfcG90YWJpbGl0eSkKYGBgCgojIyMjIHJlbW92aW5nIG91dGxpZXJzOgoKUmVtb3Zpbmcgb3V0bGllcnMgZnJvbSBhIGRhdGFzZXQgaXMgY3JpdGljYWwgZm9yIGFzc3VyaW5nIHRoZSBxdWFsaXR5IGFuZCByZWxpYWJpbGl0eSBvZiBzdGF0aXN0aWNhbCBhbmFseXNpcyBhbmQgbWFjaGluZSBsZWFybmluZyBtb2RlbHMuIFdlIGZvdW5kIGFsbCBvdXRsaWVycyBpbiB0aGUgbnVtZXJpY2FsIGF0dHJpYnV0ZXMgYW5kIHN1YnNlcXVlbnRseSBlbGltaW5hdGVkIHRoZSByb3dzIGNvbnRhaW5pbmcgdGhlIG91dGxpZXJzLgoKIyMjIC1waAoKYGBge3J9CnN1bW1hcnkod2F0ZXJfcG90YWJpbGl0eSRwaCkKcXVhcnRpbGVzIDwtIHF1YW50aWxlKHdhdGVyX3BvdGFiaWxpdHkkcGgsIHByb2JzID0gYyguMjUsIC43NSksIG5hLnJtID0gRkFMU0UpCnF1YXJ0aWxlcwppcXIgPC0gSVFSKHdhdGVyX3BvdGFiaWxpdHkkcGgpCmlxcgpsb3dlciA8LSBxdWFydGlsZXNbMV0gLSAxLjUqaXFyCmxvd2VyCnVwcGVyIDwtIHF1YXJ0aWxlc1syXSArIDEuNSppcXIKdXBwZXIKCmJveHBsb3QocGggfiBQb3RhYmlsaXR5LCBkYXRhID0gd2F0ZXJfcG90YWJpbGl0eSkKCnJlcGVhdCB7CiAgb3V0X3ZhbCA8LSBib3hwbG90KHdhdGVyX3BvdGFiaWxpdHkkcGgsIHlsYWIgPSAncGgnKSRvdXQKICBvdXRfdmFsCiAgb3V0X3Jvd3MgPC0gd2hpY2god2F0ZXJfcG90YWJpbGl0eSRwaCAlaW4lIGMob3V0X3ZhbCkpCiAgb3V0X3Jvd3MKICAKICBpZihzdW0ob3V0X3Jvd3MpID4gMCkgd2F0ZXJfcG90YWJpbGl0eSA8LSB3YXRlcl9wb3RhYmlsaXR5Wy1vdXRfcm93cyxdCiAgZWxzZSB7YnJlYWt9Cn0Kc3VtbWFyeSh3YXRlcl9wb3RhYmlsaXR5JHBoKQoKIy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KYGBgCgojIyMgLUhhcmRuZXNzCgpgYGB7cn0Kc3VtbWFyeSh3YXRlcl9wb3RhYmlsaXR5JEhhcmRuZXNzKQpxdWFydGlsZXMgPC0gcXVhbnRpbGUod2F0ZXJfcG90YWJpbGl0eSRIYXJkbmVzcywgcHJvYnMgPSBjKC4yNSwgLjc1KSwgbmEucm0gPSBGQUxTRSkKcXVhcnRpbGVzCmlxciA8LSBJUVIod2F0ZXJfcG90YWJpbGl0eSRIYXJkbmVzcykKaXFyCmxvd2VyIDwtIHF1YXJ0aWxlc1sxXSAtIDEuNSppcXIKbG93ZXIKdXBwZXIgPC0gcXVhcnRpbGVzWzJdICsgMS41Kmlxcgp1cHBlcgoKYm94cGxvdChIYXJkbmVzcyB+IFBvdGFiaWxpdHksIGRhdGEgPSB3YXRlcl9wb3RhYmlsaXR5KQoKcmVwZWF0IHsKICBvdXRfdmFsIDwtIGJveHBsb3Qod2F0ZXJfcG90YWJpbGl0eSRIYXJkbmVzcywgeWxhYiA9ICdIYXJkbmVzcycpJG91dAogIG91dF92YWwKICBvdXRfcm93cyA8LSB3aGljaCh3YXRlcl9wb3RhYmlsaXR5JEhhcmRuZXNzICVpbiUgYyhvdXRfdmFsKSkKICBvdXRfcm93cwoKICBpZihzdW0ob3V0X3Jvd3MpID4gMCkgd2F0ZXJfcG90YWJpbGl0eSA8LSB3YXRlcl9wb3RhYmlsaXR5Wy1vdXRfcm93cyxdCiAgZWxzZSB7YnJlYWt9Cn0Kc3VtbWFyeSh3YXRlcl9wb3RhYmlsaXR5JEhhcmRuZXNzKQoKIy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KYGBgCgojIyMgLVNvbGlkcwoKYGBge3J9CnN1bW1hcnkod2F0ZXJfcG90YWJpbGl0eSRTb2xpZHMpCnF1YXJ0aWxlcyA8LSBxdWFudGlsZSh3YXRlcl9wb3RhYmlsaXR5JFNvbGlkcywgcHJvYnMgPSBjKC4yNSwgLjc1KSwgbmEucm0gPSBGQUxTRSkKcXVhcnRpbGVzCmlxciA8LSBJUVIod2F0ZXJfcG90YWJpbGl0eSRTb2xpZHMpCmlxcgpsb3dlciA8LSBxdWFydGlsZXNbMV0gLSAxLjUqaXFyCmxvd2VyCnVwcGVyIDwtIHF1YXJ0aWxlc1syXSArIDEuNSppcXIKdXBwZXIKCmJveHBsb3QoU29saWRzIH4gUG90YWJpbGl0eSwgZGF0YSA9IHdhdGVyX3BvdGFiaWxpdHkpCgpyZXBlYXQgewogIG91dF92YWwgPC0gYm94cGxvdCh3YXRlcl9wb3RhYmlsaXR5JFNvbGlkcywgeWxhYiA9ICdTb2xpZHMnKSRvdXQKICBvdXRfdmFsCiAgb3V0X3Jvd3MgPC0gd2hpY2god2F0ZXJfcG90YWJpbGl0eSRTb2xpZHMgJWluJSBjKG91dF92YWwpKQogIG91dF9yb3dzCgogIGlmKHN1bShvdXRfcm93cykgPiAwKSB3YXRlcl9wb3RhYmlsaXR5IDwtIHdhdGVyX3BvdGFiaWxpdHlbLW91dF9yb3dzLF0KICBlbHNlIHticmVha30KfQpzdW1tYXJ5KHdhdGVyX3BvdGFiaWxpdHkkU29saWRzKQoKIy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KYGBgCgojIyMgLUNobG9yYW1pbmVzCgpgYGB7cn0Kc3VtbWFyeSh3YXRlcl9wb3RhYmlsaXR5JENobG9yYW1pbmVzKQpxdWFydGlsZXMgPC0gcXVhbnRpbGUod2F0ZXJfcG90YWJpbGl0eSRDaGxvcmFtaW5lcywgcHJvYnMgPSBjKC4yNSwgLjc1KSwgbmEucm0gPSBGQUxTRSkKcXVhcnRpbGVzCmlxciA8LSBJUVIod2F0ZXJfcG90YWJpbGl0eSRDaGxvcmFtaW5lcykKaXFyCmxvd2VyIDwtIHF1YXJ0aWxlc1sxXSAtIDEuNSppcXIKbG93ZXIKdXBwZXIgPC0gcXVhcnRpbGVzWzJdICsgMS41Kmlxcgp1cHBlcgoKYm94cGxvdChDaGxvcmFtaW5lcyB+IFBvdGFiaWxpdHksIGRhdGEgPSB3YXRlcl9wb3RhYmlsaXR5KQoKcmVwZWF0IHsKICBvdXRfdmFsIDwtIGJveHBsb3Qod2F0ZXJfcG90YWJpbGl0eSRDaGxvcmFtaW5lcywgeWxhYiA9ICdDaGxvcmFtaW5lcycpJG91dAogIG91dF92YWwKICBvdXRfcm93cyA8LSB3aGljaCh3YXRlcl9wb3RhYmlsaXR5JENobG9yYW1pbmVzICVpbiUgYyhvdXRfdmFsKSkKICBvdXRfcm93cwoKICBpZihzdW0ob3V0X3Jvd3MpID4gMCkgd2F0ZXJfcG90YWJpbGl0eSA8LSB3YXRlcl9wb3RhYmlsaXR5Wy1vdXRfcm93cyxdCiAgZWxzZSB7YnJlYWt9Cn0Kc3VtbWFyeSh3YXRlcl9wb3RhYmlsaXR5JENobG9yYW1pbmVzKQoKIy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KCmBgYAoKIyMjIC1TdWxmYXRlCgpgYGB7cn0Kc3VtbWFyeSh3YXRlcl9wb3RhYmlsaXR5JFN1bGZhdGUpCnF1YXJ0aWxlcyA8LSBxdWFudGlsZSh3YXRlcl9wb3RhYmlsaXR5JFN1bGZhdGUsIHByb2JzID0gYyguMjUsIC43NSksIG5hLnJtID0gRkFMU0UpCnF1YXJ0aWxlcwppcXIgPC0gSVFSKHdhdGVyX3BvdGFiaWxpdHkkU3VsZmF0ZSkKaXFyCmxvd2VyIDwtIHF1YXJ0aWxlc1sxXSAtIDEuNSppcXIKbG93ZXIKdXBwZXIgPC0gcXVhcnRpbGVzWzJdICsgMS41Kmlxcgp1cHBlcgoKYm94cGxvdChTdWxmYXRlIH4gUG90YWJpbGl0eSwgZGF0YSA9IHdhdGVyX3BvdGFiaWxpdHkpCgpyZXBlYXQgewogIG91dF92YWwgPC0gYm94cGxvdCh3YXRlcl9wb3RhYmlsaXR5JFN1bGZhdGUsIHlsYWIgPSAnU3VsZmF0ZScpJG91dAogIG91dF92YWwKICBvdXRfcm93cyA8LSB3aGljaCh3YXRlcl9wb3RhYmlsaXR5JFN1bGZhdGUgJWluJSBjKG91dF92YWwpKQogIG91dF9yb3dzCgogIGlmKHN1bShvdXRfcm93cykgPiAwKSB3YXRlcl9wb3RhYmlsaXR5IDwtIHdhdGVyX3BvdGFiaWxpdHlbLW91dF9yb3dzLF0KICBlbHNlIHticmVha30KfQpzdW1tYXJ5KHdhdGVyX3BvdGFiaWxpdHkkU3VsZmF0ZSkKCiMtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCgpgYGAKCiMjIyAtQ29uZHVjdGl2aXR5CgpgYGB7cn0Kc3VtbWFyeSh3YXRlcl9wb3RhYmlsaXR5JENvbmR1Y3Rpdml0eSkKcXVhcnRpbGVzIDwtIHF1YW50aWxlKHdhdGVyX3BvdGFiaWxpdHkkQ29uZHVjdGl2aXR5LCBwcm9icyA9IGMoLjI1LCAuNzUpLCBuYS5ybSA9IEZBTFNFKQpxdWFydGlsZXMKaXFyIDwtIElRUih3YXRlcl9wb3RhYmlsaXR5JENvbmR1Y3Rpdml0eSkKaXFyCmxvd2VyIDwtIHF1YXJ0aWxlc1sxXSAtIDEuNSppcXIKbG93ZXIKdXBwZXIgPC0gcXVhcnRpbGVzWzJdICsgMS41Kmlxcgp1cHBlcgoKYm94cGxvdChDb25kdWN0aXZpdHkgfiBQb3RhYmlsaXR5LCBkYXRhID0gd2F0ZXJfcG90YWJpbGl0eSkKCnJlcGVhdCB7CiAgb3V0X3ZhbCA8LSBib3hwbG90KHdhdGVyX3BvdGFiaWxpdHkkQ29uZHVjdGl2aXR5LCB5bGFiID0gJ0NvbmR1Y3Rpdml0eScpJG91dAogIG91dF92YWwKICBvdXRfcm93cyA8LSB3aGljaCh3YXRlcl9wb3RhYmlsaXR5JENvbmR1Y3Rpdml0eSAlaW4lIGMob3V0X3ZhbCkpCiAgb3V0X3Jvd3MKCiAgaWYoc3VtKG91dF9yb3dzKSA+IDApIHdhdGVyX3BvdGFiaWxpdHkgPC0gd2F0ZXJfcG90YWJpbGl0eVstb3V0X3Jvd3MsXQogIGVsc2Uge2JyZWFrfQp9CnN1bW1hcnkod2F0ZXJfcG90YWJpbGl0eSRDb25kdWN0aXZpdHkpCgojLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQpgYGAKCiMjIyAtT3JnYW5pY19jYXJib24KCmBgYHtyfQpzdW1tYXJ5KHdhdGVyX3BvdGFiaWxpdHkkT3JnYW5pY19jYXJib24pCnF1YXJ0aWxlcyA8LSBxdWFudGlsZSh3YXRlcl9wb3RhYmlsaXR5JE9yZ2FuaWNfY2FyYm9uLCBwcm9icyA9IGMoLjI1LCAuNzUpLCBuYS5ybSA9IEZBTFNFKQpxdWFydGlsZXMKaXFyIDwtIElRUih3YXRlcl9wb3RhYmlsaXR5JE9yZ2FuaWNfY2FyYm9uKQppcXIKbG93ZXIgPC0gcXVhcnRpbGVzWzFdIC0gMS41Kmlxcgpsb3dlcgp1cHBlciA8LSBxdWFydGlsZXNbMl0gKyAxLjUqaXFyCnVwcGVyCgpib3hwbG90KE9yZ2FuaWNfY2FyYm9uIH4gUG90YWJpbGl0eSwgZGF0YSA9IHdhdGVyX3BvdGFiaWxpdHkpCgpyZXBlYXQgewogIG91dF92YWwgPC0gYm94cGxvdCh3YXRlcl9wb3RhYmlsaXR5JE9yZ2FuaWNfY2FyYm9uLCB5bGFiID0gJ09yZ2FuaWNfY2FyYm9uJykkb3V0CiAgb3V0X3ZhbAogIG91dF9yb3dzIDwtIHdoaWNoKHdhdGVyX3BvdGFiaWxpdHkkT3JnYW5pY19jYXJib24gJWluJSBjKG91dF92YWwpKQogIG91dF9yb3dzCgogIGlmKHN1bShvdXRfcm93cykgPiAwKSB3YXRlcl9wb3RhYmlsaXR5IDwtIHdhdGVyX3BvdGFiaWxpdHlbLW91dF9yb3dzLF0KICBlbHNlIHticmVha30KfQpzdW1tYXJ5KHdhdGVyX3BvdGFiaWxpdHkkT3JnYW5pY19jYXJib24pCgojLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQpgYGAKCiMjIyAtVHJpaGFsb21ldGhhbmVzCgpgYGB7cn0Kc3VtbWFyeSh3YXRlcl9wb3RhYmlsaXR5JFRyaWhhbG9tZXRoYW5lcykKcXVhcnRpbGVzIDwtIHF1YW50aWxlKHdhdGVyX3BvdGFiaWxpdHkkVHJpaGFsb21ldGhhbmVzLCBwcm9icyA9IGMoLjI1LCAuNzUpLCBuYS5ybSA9IEZBTFNFKQpxdWFydGlsZXMKaXFyIDwtIElRUih3YXRlcl9wb3RhYmlsaXR5JFRyaWhhbG9tZXRoYW5lcykKaXFyCmxvd2VyIDwtIHF1YXJ0aWxlc1sxXSAtIDEuNSppcXIKbG93ZXIKdXBwZXIgPC0gcXVhcnRpbGVzWzJdICsgMS41Kmlxcgp1cHBlcgoKYm94cGxvdChUcmloYWxvbWV0aGFuZXMgfiBQb3RhYmlsaXR5LCBkYXRhID0gd2F0ZXJfcG90YWJpbGl0eSkKCnJlcGVhdCB7CiAgb3V0X3ZhbCA8LSBib3hwbG90KHdhdGVyX3BvdGFiaWxpdHkkVHJpaGFsb21ldGhhbmVzLCB5bGFiID0gJ1RyaWhhbG9tZXRoYW5lcycpJG91dAogIG91dF92YWwKICBvdXRfcm93cyA8LSB3aGljaCh3YXRlcl9wb3RhYmlsaXR5JFRyaWhhbG9tZXRoYW5lcyAlaW4lIGMob3V0X3ZhbCkpCiAgb3V0X3Jvd3MKCiAgaWYoc3VtKG91dF9yb3dzKSA+IDApIHdhdGVyX3BvdGFiaWxpdHkgPC0gd2F0ZXJfcG90YWJpbGl0eVstb3V0X3Jvd3MsXQogIGVsc2Uge2JyZWFrfQp9CnN1bW1hcnkod2F0ZXJfcG90YWJpbGl0eSRUcmloYWxvbWV0aGFuZXMpCgojLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQpgYGAKCiMjIyAtVHVyYmlkaXR5CgpgYGB7cn0Kc3VtbWFyeSh3YXRlcl9wb3RhYmlsaXR5JFR1cmJpZGl0eSkKcXVhcnRpbGVzIDwtIHF1YW50aWxlKHdhdGVyX3BvdGFiaWxpdHkkVHVyYmlkaXR5LCBwcm9icyA9IGMoLjI1LCAuNzUpLCBuYS5ybSA9IEZBTFNFKQpxdWFydGlsZXMKaXFyIDwtIElRUih3YXRlcl9wb3RhYmlsaXR5JFR1cmJpZGl0eSkKaXFyCmxvd2VyIDwtIHF1YXJ0aWxlc1sxXSAtIDEuNSppcXIKbG93ZXIKdXBwZXIgPC0gcXVhcnRpbGVzWzJdICsgMS41Kmlxcgp1cHBlcgoKYm94cGxvdChUdXJiaWRpdHkgfiBQb3RhYmlsaXR5LCBkYXRhID0gd2F0ZXJfcG90YWJpbGl0eSkKCnJlcGVhdCB7CiAgb3V0X3ZhbCA8LSBib3hwbG90KHdhdGVyX3BvdGFiaWxpdHkkVHVyYmlkaXR5LCB5bGFiID0gJ1R1cmJpZGl0eScpJG91dAogIG91dF92YWwKICBvdXRfcm93cyA8LSB3aGljaCh3YXRlcl9wb3RhYmlsaXR5JFR1cmJpZGl0eSAlaW4lIGMob3V0X3ZhbCkpCiAgb3V0X3Jvd3MKCiAgaWYoc3VtKG91dF9yb3dzKSA+IDApIHdhdGVyX3BvdGFiaWxpdHkgPC0gd2F0ZXJfcG90YWJpbGl0eVstb3V0X3Jvd3MsXQogIGVsc2Uge2JyZWFrfQp9CnN1bW1hcnkod2F0ZXJfcG90YWJpbGl0eSRUdXJiaWRpdHkpCmBgYAoKIyMjIEFmdGVyIHJlbW92aW5nIG91dGxpZXJzOgoKYGBge3J9CmRpbSh3YXRlcl9wb3RhYmlsaXR5KQpzdHIod2F0ZXJfcG90YWJpbGl0eSkKaGVhZCh3YXRlcl9wb3RhYmlsaXR5KQpgYGAKCiMjIyBDaGVja2luZyBmb3IgaW1iYWxhbmNlZCBkYXRhc2V0OgoKYGBge3J9CmNsYXNzX2Rpc3RyaWJ1dGlvbiA8LSB0YWJsZSh3YXRlcl9wb3RhYmlsaXR5JFBvdGFiaWxpdHkpCnByaW50KGNsYXNzX2Rpc3RyaWJ1dGlvbikKCiMgQ2hlY2sgaWYgdGhlIGRhdGFzZXQgaXMgYmFsYW5jZWQKaXNfYmFsYW5jZWQgPC0gZGlmZihjbGFzc19kaXN0cmlidXRpb24pID09IDAKaWYgKGlzX2JhbGFuY2VkKSB7CiAgcHJpbnQoIlRoZSBkYXRhc2V0IGlzIGJhbGFuY2VkLiIpCn0gZWxzZSB7CiAgcHJpbnQoIlRoZSBkYXRhc2V0IGlzIGltYmFsYW5jZWQuIikKfQpgYGAKCmBgYHtyfQpib3hwbG90KHdhdGVyX3BvdGFiaWxpdHkkcGgsIHlsYWIgPSAncGgnKSRvdXQKYm94cGxvdCh3YXRlcl9wb3RhYmlsaXR5JENobG9yYW1pbmVzLCB5bGFiID0gJ0NobG9yYW1pbmVzJykkb3V0CmJveHBsb3Qod2F0ZXJfcG90YWJpbGl0eSRIYXJkbmVzcywgeWxhYiA9ICdIYXJkbmVzcycpJG91dApib3hwbG90KHdhdGVyX3BvdGFiaWxpdHkkU29saWRzLCB5bGFiID0gJ1NvbGlkcycpJG91dApib3hwbG90KHdhdGVyX3BvdGFiaWxpdHkkU3VsZmF0ZSwgeWxhYiA9ICdTdWxmYXRlJykkb3V0CmJveHBsb3Qod2F0ZXJfcG90YWJpbGl0eSRDb25kdWN0aXZpdHksIHlsYWIgPSAnQ29uZHVjdGl2aXR5Jykkb3V0CmJveHBsb3Qod2F0ZXJfcG90YWJpbGl0eSRPcmdhbmljX2NhcmJvbiwgeWxhYiA9ICdPcmdhbmljX2NhcmJvbicpJG91dApib3hwbG90KHdhdGVyX3BvdGFiaWxpdHkkVHJpaGFsb21ldGhhbmVzLCB5bGFiID0gJ1RyaWhhbG9tZXRoYW5lcycpJG91dApib3hwbG90KHdhdGVyX3BvdGFiaWxpdHkkVHVyYmlkaXR5LCB5bGFiID0gJ1R1cmJpZGl0eScpJG91dApgYGAKCiMjIENoYXJ0czoKCnZpc3VhbCByZXByZXNlbnRhdGlvbiBvZiBkYXRhIHRoYXQgaGVscCB1cyB1bmRlcnN0YW5kIGFuZCBhbmFseXplIGluZm9ybWF0aW9uIG1vcmUgZWFzaWx5LiBUaGV5IGNhbiBiZSB1c2VkIHRvIGRpc3BsYXkgdHJlbmRzLCBjb21wYXJpc29ucywgYW5kIHJlbGF0aW9uc2hpcHMgYmV0d2VlbiBkaWZmZXJlbnQgdmFyaWFibGVzLiBUaGVyZSBhcmUgdmFyaW91cyB0eXBlcyBvZiBjaGFydHMsIHN1Y2ggYXMKCiMjIyBIaXN0b2dyYW0KClRoZSBoaXN0b2dyYW0gc2hvd3MgdGhlIGZyZXF1ZW5jeSBvZiBwaCBpbiB0aGUgZGF0YXNldDsgd2Ugbm90ZWQgdGhhdCB0aGUgbWFqb3JpdHkgb2YgdmFsdWVzIGZhbGwgd2l0aGluIHRoZSB1c3VhbCByYW5nZSwgd2hpY2ggaXMgYWJvdXQgYmV0d2VlbiA2IGFuZCA4LCBidXQgaXQgYWxzbyBzaG93cyBzZXZlcmFsIG91dGxpZXJzLgoKYGBge3J9Cmhpc3Qod2F0ZXJfcG90YWJpbGl0eSRwaCkKaGlzdCh3YXRlcl9wb3RhYmlsaXR5JENobG9yYW1pbmVzKQpoaXN0KHdhdGVyX3BvdGFiaWxpdHkkSGFyZG5lc3MpCmhpc3Qod2F0ZXJfcG90YWJpbGl0eSRTb2xpZHMpCmhpc3Qod2F0ZXJfcG90YWJpbGl0eSRTdWxmYXRlKQpoaXN0KHdhdGVyX3BvdGFiaWxpdHkkQ29uZHVjdGl2aXR5KQpoaXN0KHdhdGVyX3BvdGFiaWxpdHkkT3JnYW5pY19jYXJib24pCmhpc3Qod2F0ZXJfcG90YWJpbGl0eSRUcmloYWxvbWV0aGFuZXMpCmhpc3Qod2F0ZXJfcG90YWJpbGl0eSRUdXJiaWRpdHkpCmBgYAoKIyMjIEJhciBQbG90Cgp0aGUgYmFyIHBsb3QgcmVwcmVzZW50IGhvdyBwaCBsZXZlbHMgYWZmZWN0IHdhdGVyIHBvcnRhYmlsaXR5IGluIHRoZSBkYXRhc2V0IGl0IGluZGljYXRlcyB0aGF0IHBoIGxldmVsIGFib3ZlIDEwIGlzIG5vdCBwb3J0aWJhbCBhbmQgaHVtYW5zIGNhbnQgY29uc3VtZSBpdAoKYGBge3J9CnRhYiA8LSB3YXRlcl9wb3RhYmlsaXR5JFBvdGFiaWxpdHkgJT4lIHRhYmxlKCkKdHh0IDwtIHBhc3RlMCh0YWIpIApiYiA8LSB3YXRlcl9wb3RhYmlsaXR5JHBoICU+JSB0YWJsZSgpICU+JSBiYXJwbG90KCBtYWluPSdwaCcsY29sPWMoJ3BpbmsnKSkKYmIgPC0gd2F0ZXJfcG90YWJpbGl0eSRQb3RhYmlsaXR5ICU+JSB0YWJsZSgpICU+JSBiYXJwbG90KCBtYWluPSdQb3RhYmlsaXR5Jyx5bGFiPSdGcmVxdWVuY3knLGNvbD1jKCdwaW5rJywgJ2xpZ2h0Ymx1ZScpKQp0ZXh0KGJiLCB0YWIvMiwgbGFiZWxzPXR4dCwgY2V4PTEpCgpgYGAKCiMjIyBTY2F0dGVyIFBsb3QKClRoaXMgc2NhdHRlciBkZW1vbnN0cmF0ZXMgdGhlIGNvcnJlbGF0aW9uIGFuZCBwcm9wb3J0aW9uYWxpdHkgYmV0d2VlbiB0aGUgdHdvIHF1YWxpdGllcywgYWxsb3dpbmcgdXMgdG8gZXN0YWJsaXNoIHdoZXRoZXIgb3Igbm90IHR1cmJpZGl0eSBhbmQgcEggYXJlIGNvbm5lY3RlZC4KCmBgYHtyfQp3aXRoKHdhdGVyX3BvdGFiaWxpdHksIHBsb3QoVHJpaGFsb21ldGhhbmVzLCBwaCwgY29sID0gUG90YWJpbGl0eSwgcGNoID0gYXMubnVtZXJpYyhQb3RhYmlsaXR5KSkpCmBgYAoKIyMjIFJlbW92ZSBSZWR1bmRhbnQgRmVhdHVyZXM6CgpUaGlzIHdpbGwgZmluZCB0aGUgY29ycmVsYXRpb24gYmV0d2VlbiB0aGUgZmVhdHVyZXMgYW5kIHJlcHJlc2VudCBpdCBpbiBoZWF0bWFwCgpgYGB7cn0KY29ycmVsYXRpb25fbWF0cml4IDwtIGNvcih3YXRlcl9wb3RhYmlsaXR5WywxOjldKQpoaWdoX2NvcnJlbGF0aW9uX2ZlYXR1cmVzIDwtIGZpbmRDb3JyZWxhdGlvbihjb3JyZWxhdGlvbl9tYXRyaXgsIGN1dG9mZiA9IDAuNSkKcHJpbnQoaGlnaF9jb3JyZWxhdGlvbl9mZWF0dXJlcykKYGBgCgojIyMgSGVhdG1hcDoKCkEgcG93ZXJmdWwgdmlzdWFsaXphdGlvbiB0b29sIHRoYXQgYWxsb3dzIGZvciBhIHF1aWNrIGFuZCBpbnR1aXRpdmUgaW50ZXJwcmV0YXRpb24gb2YgdGhlIHJlbGF0aW9uc2hpcHMgYmV0d2VlbiBudW1lcmljIHZhcmlhYmxlcy4gSXQgcHJvdmlkZXMgdmFsdWFibGUgaW5zaWdodHMgaW50byB0aGUgc3RydWN0dXJlIGFuZCBkZXBlbmRlbmNpZXMgd2l0aGluIHlvdXIgZGF0YXNldC4KCmBgYHtyfQpoZWF0bWFwKGNvcnJlbGF0aW9uX21hdHJpeCkKCmBgYAoKd2UgcmVtb3ZlIHRoZSBjb3JyZWxhdGlvbiBiZXR3ZWVuIHRoZSBmZWF0dXJlcyBhbmQgcmVwcmVzZW50IGl0IGluIGhlYXQgbWFwCgojIyMgRmVhdHVyZSBzZWxlY3Rpb246CgojIyMgRmVhdHVyZSBzZWxlY3Rpb24gaXMgZGVlbWVkIHVubmVjZXNzYXJ5IGZvciBvdXIgZGF0YXNldCwgYXMgZWFjaCBhdHRyaWJ1dGUgaXMgZGVlbWVkIHRvIHByb3ZpZGUgY3J1Y2lhbCwgZGlzdGluY3QgaW5mb3JtYXRpb24gcmVsYXRlZCB0byB0aGUgY2hvc2VuIHZhcmlhYmxlLiBUaGUgcmVhc29uaW5nIGJlaGluZCB0aGlzIGRlY2lzaW9uIGlzIHRoYXQgZWxpbWluYXRpbmcgYW55IGF0dHJpYnV0ZSB0aHJvdWdoIGZlYXR1cmUgc2VsZWN0aW9uIGNvdWxkIHBvdGVudGlhbGx5IGxlYWQgdG8gdGhlIGxvc3Mgb2Ygdml0YWwgZGF0YS4gQWRkaXRpb25hbGx5LCBjZXJ0YWluIG1hY2hpbmUgbGVhcm5pbmcgYWxnb3JpdGhtcyBwb3NzZXNzIHRoZSBjYXBhYmlsaXR5IHRvIGlkZW50aWZ5IGludHJpY2F0ZSBpbnRlcmFjdGlvbnMgYW5kIGF0dHJpYnV0ZSBjb3JyZWxhdGlvbnMuIEJ5IGluY2x1ZGluZyBhbGwgdmFyaWFibGVzIGluIHRoZSBtb2RlbCwgd2UgYWltIHRvIGVuYWJsZSB0aGUgbGVhcm5pbmcgYW5kIGV4cGxvaXRhdGlvbiBvZiBjb21wbGV4IHBhdHRlcm5zIHdpdGhpbiB0aGUgZGF0YXNldCwgcG90ZW50aWFsbHkgZW5oYW5jaW5nIHByZWRpY3RpdmUgcGVyZm9ybWFuY2UsIGVzcGVjaWFsbHkgY29uc2lkZXJpbmcgdGhlIGRhdGFzZXQncyBzdWJzdGFudGlhbCBzaXplIHdpdGjCoDEwwqBjb2x1bW5zCgppdCBpcyBjaG9vc2luZyB0aGUgbW9zdCByZWxldmFudCBmZWF0dXJlcyBmcm9tIGEgZGF0YXNldCB0byBlbmhhbmNlIG1vZGVsIHBlcmZvcm1hbmNlLCByZWR1Y2Ugb3ZlcmZpdHRpbmcsIGFuZCBpbXByb3ZlIGNvbXB1dGF0aW9uYWwgZWZmaWNpZW5jeS4KClJhbmtpbmcgZmVhdHVyZXMgYnkgaW1wb3J0YW5jZSBpcyBhIHRlY2huaXF1ZSB1c2VkIHRvIGlkZW50aWZ5IHRoZSBtb3N0IGluZmx1ZW50aWFsIHZhcmlhYmxlcyBpbiBhIGRhdGFzZXQgZm9yIHByZWRpY3RpbmcgYSB0YXJnZXQgdmFyaWFibGUuIFRoaXMgcHJvY2VzcyBoZWxwcyB1bmRlcnN0YW5kIHdoaWNoIGZlYXR1cmVzIGltcGFjdCB0aGUgbW9kZWwncyBwZXJmb3JtYW5jZSBtb3N0IGJ5IHJhbmtpbmcgZmVhdHVyZXMgYnkgaW1wb3J0YW5jZS4KClJlbW92aW5nIHJlZHVuZGFudCBmZWF0dXJlcyBtZWFucyBlbGltaW5hdGluZyB2YXJpYWJsZXMgb3IgZmVhdHVyZXMgZnJvbSBhIGRhdGFzZXQgdGhhdCBkbyBub3QgcHJvdmlkZSBhZGRpdGlvbmFsIG9yIHVuaXF1ZcKgaW5mb3JtYXRpb24uCgojIyMgUmFuayBGZWF0dXJlcyBCeSBJbXBvcnRhbmNlOgoKcmFua2luZyBmZWF0dXJlcyBieSBpbXBvcnRhbmNlIGlzIGEgdGVjaG5pcXVlIHVzZWQgdG8gaWRlbnRpZnkgdGhlIG1vc3QgaW5mbHVlbnRpYWwgdmFyaWFibGVzIGluIGEgZGF0YXNldCBmb3IgcHJlZGljdGluZyBhIHRhcmdldCB2YXJpYWJsZS4gVGhpcyBwcm9jZXNzIGhlbHBzIGluIHVuZGVyc3RhbmRpbmcgd2hpY2ggZmVhdHVyZXMgaGF2ZSB0aGUgbW9zdCBpbXBhY3Qgb24gdGhlIG1vZGVsJ3MgcGVyZm9ybWFuY2UuIEJ5IHJhbmtpbmcgZmVhdHVyZXMgYnkgaW1wb3J0YW5jZS4KCmBgYHtyLCB3YXJuaW5nPUZBTFNFfQojdHJhaW4gcmFuZG9tIGZvcmVzdCBtb2RlbCBhbmQgY2FsY3VsYXRlIGZlYXR1cmUgaW1wb3J0YW5jZQpyZiA9IHJhbmRvbUZvcmVzdCh4PSB3YXRlcl9wb3RhYmlsaXR5WywxOjldLHk9IHdhdGVyX3BvdGFiaWxpdHlbLDEwXSkKdmFyX2ltcCA8LSB2YXJJbXAocmYsIHNjYWxlID0gRkFMU0UpCiNzb3J0IHRoZSBzY29yZSBpbiBkZWNyZWFzaW5nIG9yZGVyCnZhcl9pbXBfZGYgPC0gZGF0YS5mcmFtZShjYmluZCh2YXJpYWJsZSA9IHJvd25hbWVzKHZhcl9pbXApLCBzY29yZSA9IHZhcl9pbXBbLDFdKSkKdmFyX2ltcF9kZiRzY29yZSA8LSBhcy5kb3VibGUodmFyX2ltcF9kZiRzY29yZSkKdmFyX2ltcF9kZltvcmRlcih2YXJfaW1wX2RmJHNjb3JlLGRlY3JlYXNpbmcgPSBUUlVFKSxdCgpnZ3Bsb3QodmFyX2ltcF9kZiwgYWVzKHg9cmVvcmRlcih2YXJpYWJsZSwgc2NvcmUpLCB5PXNjb3JlKSkgKyAKICBnZW9tX3BvaW50KCkgKwogIGdlb21fc2VnbWVudChhZXMoeD12YXJpYWJsZSx4ZW5kPXZhcmlhYmxlLHk9MCx5ZW5kPXNjb3JlKSkgKwogIHlsYWIoIkluY05vZGVQdXJpdHkiKSArCiAgeGxhYigiVmFyaWFibGUgTmFtZSIpICsKICBjb29yZF9mbGlwKCkKYGBgCgojIyMgUmVjdXJzaXZlIEZlYXR1cmUgZWxpbWluYXRpb246CgppcyBhIGZlYXR1cmUgc2VsZWN0aW9uIHRlY2huaXF1ZSB0aGF0IHJlY3Vyc2l2ZWx5IHJlbW92ZXMgbGVzcyBpbXBvcnRhbnQgZmVhdHVyZXMgZnJvbSBhIG1vZGVsIHVudGlsIHRoZSBvcHRpbWFsIHN1YnNldCBpcyBpZGVudGlmaWVkLiBJdCBpbnZvbHZlcyByZXBlYXRlZGx5IHRyYWluaW5nIHRoZSBtb2RlbCwgcmFua2luZyBmZWF0dXJlcyBiYXNlZCBvbiB0aGVpciBpbXBvcnRhbmNlLCBhbmQgZWxpbWluYXRpbmcgdGhlIGxlYXN0IGltcG9ydGFudCBvbmVzLgoKYGBge3J9CnNldC5zZWVkKDE5NTgpCmNvbnRyb2wgPC0gcmZlQ29udHJvbChmdW5jdGlvbnM9cmZGdW5jcywgbWV0aG9kPSJjdiIsbnVtYmVyPTEwKQojIHJ1biB0aGUgUkZFIGFsZ29yaXRobSAKcmZlX21vZGVsIDwtIHJmZSh4PSB3YXRlcl9wb3RhYmlsaXR5WywxOjldLHk9IHdhdGVyX3BvdGFiaWxpdHlbLDEwXSwgc2l6ZXM9YygxOjkpLCByZmVDb250cm9sPWNvbnRyb2wpIAojIHN1bW1hcml6ZSB0aGUgcmVzdWx0cyAKcHJpbnQocmZlX21vZGVsKSAKIyBsaXN0IHRoZSBjaG9zZW4gZmVhdHVyZXMgCnByZWRpY3RvcnMocmZlX21vZGVsKSAKIyBwbG90IHRoZSByZXN1bHRzIApwbG90KHJmZV9tb2RlbCwgdHlwZT1jKCJnIiwgIm8iKSkKYGBgCgojIyMgTm9ybWxpemF0aW9uCgpOb3JtYWxpemF0aW9uIHJlZmVycyB0byB0aGUgcHJvY2VzcyBvZiBzY2FsaW5nIHZhcmlhYmxlcyB0byBoYXZlIGEgY29tbW9uIHJhbmdlLiBJdCBoZWxwcyBpbiBjb21wYXJpbmcgdmFyaWFibGVzIHdpdGggZGlmZmVyZW50IHNjYWxlcy4KCmBgYHtyfQp3cDwtIHdhdGVyX3BvdGFiaWxpdHkKbm9ybWFsaXplPWZ1bmN0aW9uKHgpe3JldHVybiAoKHgtbWluKHgpKS8obWF4KHgpKSl9CndwJFNvbGlkcz1ub3JtYWxpemUod3AkU29saWRzKQpgYGAKClRoZSBzb2xpZHMgYXR0cmlidXRlIHdpbGwgY3JlYXRlIGNyaXRpY2FsIGNoYWxsZW5nZXMgYmVjYXVzZSBvZiB0aGUgdmFzdCBhbmQgZGl2ZXJ0ZWQgdmFsdWVzOiBtaW4gaXMgMzIwLjksIGFuZCBtYXggaXMgNDMxOTUuNSwgc28gd2Ugbm9ybWFsaXplZCB0aGUgc29saWRzIGJldHdlZW4gMCBhbmQgMSB0byBtYWtlIHZhbHVlcyBzbWFsbGVyIGFuZCBtb3JlIHJlYXNvbmFibGUuCgojIyMgRGlzY3JldGl6YXRpb246CgpEaXNjcmV0aXphdGlvbiBpcyB0aGUgcHJvY2VzcyBvZiB0cmFuc2Zvcm1pbmcgY29udGludW91cyB2YXJpYWJsZXMgaW50byBkaXNjcmV0ZSBvciBjYXRlZ29yaWNhbCB2YXJpYWJsZXMuIEl0IGNhbiBiZSB1c2VmdWwgZm9yIGFuYWx5emluZyBkYXRhIHdpdGggbWFueSB1bmlxdWUgdmFsdWVzIG9yIHNpbXBsaWZ5aW5nIGl0LgoKYGBge3J9Cgp3cCRwaD0gY3V0KHdwJHBoLCBicmVha3MgPSBzZXEoMywxMSxieT00KSxyaWdodD1GQUxTRSkKd3AkSGFyZG5lc3M9IGN1dCh3cCRIYXJkbmVzcywgYnJlYWtzID0gc2VxKDEyMCwyODAsYnk9NDApLHJpZ2h0PUZBTFNFKQp3cCRDaGxvcmFtaW5lcyA9IGN1dCh3cCRDaGxvcmFtaW5lcywgYnJlYWtzID0gc2VxKDMsMTEsYnk9NCkscmlnaHQgPSBGQUxTRSkKd3AkU3VsZmF0ZT0gY3V0KHdwJFN1bGZhdGUsIGJyZWFrcyA9IHNlcSgyMjAsNDQwLGJ5PTQ0KSxyaWdodD1GQUxTRSkKd3AkQ29uZHVjdGl2aXR5PSBjdXQod3AkQ29uZHVjdGl2aXR5LCBicmVha3MgPSBzZXEoMjAwLDcwMCxieT0xMDApLHJpZ2h0PUZBTFNFKQp3cCRPcmdhbmljX2NhcmJvbj0gY3V0KHdwJE9yZ2FuaWNfY2FyYm9uLCBicmVha3MgPSBzZXEoNCwyNCxieT00KSxyaWdodD1GQUxTRSkKd3AkVHJpaGFsb21ldGhhbmVzPSBjdXQod3AkVHJpaGFsb21ldGhhbmVzLCBicmVha3MgPSBzZXEoMjAsMTEwLGJ5PTEwKSxyaWdodD1GQUxTRSkKd3AkVHVyYmlkaXR5PSBjdXQod3AkVHVyYmlkaXR5LCBicmVha3MgPSBzZXEoMSw3LGJ5PTIpLHJpZ2h0PUZBTFNFKQoKcHJpbnQod3ApCmBgYAoKVGhlcmVmb3JlLCB3ZSB0cmFuc2Zvcm1lZCB0aGUgY29udGludW91cyB2YWx1ZXMgb2YgdGhlIG51bWVyaWMgYXR0cmlidXRlcyBpbnRvIGludGVydmFscyBieSBkaXZpZGluZyB0aGUgdmFsdWVzIHRvIGZhbGwgb24gb25lIG9mIHRoZSBwb3NzaWJsZSBpbnRlcnZhbCBsYWJlbHMgYnkgZGlzY3JldGl6YXRpb24uIFRoZSB2YWx1ZXMgd2lsbCBiZSBtZWFuaW5nZnVsIGFuZCBzaW1wbGVyIHRvIGNsYXNzaWZ5IG9yIHBlcmZvcm0gb3RoZXIgbWV0aG9kcyB0byBoZWxwIHVzIGxhdGVyIGluIG91ciBtb2RlbC4gU28sIEluIFRyaWhhbG9tZXRoYW5lcywgd2UgaW50ZXJ2YWxzIGJ5IGRpdmlkaW5nIHRoZSB2YWx1ZXMgYnkgMTAgdG8gaGF2ZSBsYWJlbHMgd2l0aCBlcXVhbCB3aWR0aCA6IFsyMCwzMCkgWzMwLDQwKSBbNDAsNTApIFs1MCw2MCkgWzYwLDcwKSBbNzAsODApIFs4MCw5MCkgWzkwLDEwMCkgWzEwMCwxMTApLgoKIyMjIEVuY29kaW5nCgplbmNvZGluZyBpcyB0aGUgcHJvY2VzcyBvZiBjb252ZXJ0aW5nIGNoYXJhY3RlcnMgb3Igc3RyaW5ncyBpbnRvIGEgc3BlY2lmaWMgZW5jb2RpbmcgZm9ybWF0LiBTaW5jZSB3ZSBkb24ndCBoYXZlIGEgTm9taW5hbCBhdHRyaWJ1dGUgaW4gb3VyIGRhdGFiYXNlIHdlIGNvdWxkbid0IGltcGxlbWVudCBpdC4KCmBgYHtyfQp3cApgYGAKCiMjIENsYXNzZmljYXRpb24gYW5kIENsdXN0cmluZwoKIyMjIyBJbiBvdXIgZGF0YXNldCBleHBsb3JhdGlvbiwgd2UgZW1wbG95ZWQgYm90aCBzdXBlcnZpc2VkIGFuZCB1bnN1cGVydmlzZWQgbGVhcm5pbmcgbWV0aG9kb2xvZ2llcyB0aHJvdWdoIGNsYXNzaWZpY2F0aW9uIGFuZCBjbHVzdGVyaW5nIHRlY2huaXF1ZXMuCgpGb3IgY2xhc3NpZmljYXRpb24sIHdlIGNob3NlIHRoZSBkZWNpc2lvbiB0cmVlIGFsZ29yaXRobSwgYSByZWN1cnNpdmUgYXBwcm9hY2ggY29uc3RydWN0aW5nIGEgdHJlZSBzdHJ1Y3R1cmUgd2l0aCBsZWFmIG5vZGVzIHNpZ25pZnlpbmcgZmluYWwgZGVjaXNpb25zLiBUaGUgb2JqZWN0aXZlIHdhcyB0byBwcmVkaWN0IHRoZSBjbGFzcyBsYWJlbCAocG90YWJpbGl0eSksIHdpdGggdmFsdWVzIDAgb3IgMSwgYmFzZWQgb24gYXR0cmlidXRlcyBsaWtlIHBILCBIYXJkbmVzcywgU29saWRzLCBDaGxvcmFtaW5lcywgU3VsZmF0ZSwgQ29uZHVjdGl2aXR5LCBPcmdhbmljX2NhcmJvbiwgVHJpaGFsb21ldGhhbmVzLCBhbmQgVHVyYmlkaXR5LiBUaGUgZGF0YXNldCB1bmRlcndlbnQgZGl2aXNpb24gaW50byB0cmFpbmluZyBhbmQgdGVzdGluZyBzZXRzIGZvciBjb25zdHJ1Y3RpbmcgYW5kIGV2YWx1YXRpbmcgdGhlIGRlY2lzaW9uIHRyZWUuIE1vZGVsIGV2YWx1YXRpb24gZW5jb21wYXNzZWQgbWV0cmljcyBsaWtlIGFjY3VyYWN5IGFuZCBjb3N0LXNlbnNpdGl2ZSBtZWFzdXJlcywgZ2F1Z2VkIHVzaW5nIGEgY29uZnVzaW9uIG1hdHJpeC4gT3VyIHRvb2xraXQgaW5jbHVkZWQgcGFja2FnZXMgc3VjaCBhcyAncGFydHknIGFuZCAnY2FyZXQsJyBpbmNvcnBvcmF0aW5nIG1ldGhvZHMgbGlrZSAnc2FtcGxlJyBmb3IgZGF0YSBzcGxpdHRpbmcsICdjdHJlZScgZm9yIGRlY2lzaW9uIHRyZWUgY29uc3RydWN0aW9uLCAncHJlZGljdCcgZm9yIHRlc3RpbmcgcHJlZGljdGlvbnMsIGFuZCAnY29uZnVzaW9uTWF0cml4JyBmb3IgbW9kZWwgZXZhbHVhdGlvbi4KCkluIHRoZSB1bnN1cGVydmlzZWQgY2x1c3RlcmluZyBwaGFzZSwgd2UgZXhjbHVkZWQgdGhlIGNsYXNzIGxhYmVsIGF0dHJpYnV0ZSAicG90YWJpbGl0eSIgYW5kIHV0aWxpemVkIG51bWVyaWMgYXR0cmlidXRlcyBzdWNoIGFzIHBILCBIYXJkbmVzcywgU29saWRzLCBDaGxvcmFtaW5lcywgU3VsZmF0ZSwgQ29uZHVjdGl2aXR5LCBPcmdhbmljX2NhcmJvbiwgVHJpaGFsb21ldGhhbmVzLCBhbmQgVHVyYmlkaXR5LiBFbXBsb3lpbmcgdGhlIEstbWVhbnMgYWxnb3JpdGhtLCBjbHVzdGVycyB3ZXJlIGZvcm1lZCwgZWFjaCByZXByZXNlbnRlZCBieSBhIGNlbnRlciBwb2ludCwgYW5kIG9iamVjdHMgd2VyZSBhc3NpZ25lZCB0byB0aGUgbmVhcmVzdCBjbHVzdGVyLiBGb3IgdGhpcyBwaGFzZSwgd2UgbWFkZSB1c2Ugb2YgcGFja2FnZXMgc3VjaCBhcyAnY2x1c3RlcicgYW5kICdmYWN0b2V4dHJhLCcgaW5jb3Jwb3JhdGluZyBtZXRob2RzIGxpa2UgJ3NjYWxlKCknIGZvciBkYXRhIHNjYWxpbmcsICdLbWVhbnMoKScgZm9yIGNsdXN0ZXIgY3JlYXRpb24uCgpDbHVzdGVyIHZhbGlkYXRpb24gd2FzIHBlcmZvcm1lZCB1c2luZyB0aGUgJ3NpbGhvdWV0dGUoKScgbWV0aG9kIHRvIGNhbGN1bGF0ZSBhdmVyYWdlcyBmb3IgZWFjaCBjbHVzdGVyLiBJbiBib3RoIHN1cGVydmlzZWQgYW5kIHVuc3VwZXJ2aXNlZCB0ZWNobmlxdWVzLCB3ZSBtYWludGFpbmVkIHJlc3VsdCBjb25zaXN0ZW5jeSBieSBlbXBsb3lpbmcgdGhlICdzZXQuc2VlZCgpJyBtZXRob2Qgd2l0aCB0aGUgc2FtZSByYW5kb20gbnVtYmVyIHdoZW4gZXhwZXJpbWVudGluZyB3aXRoIGRpZmZlcmVudMKgZGF0YXNldMKgc2l6ZXMuCgojIFRyYWluaW5nIHRlY2huaXF1ZQoKSW4gdGhlIHByb3ZpZGVkIGNvZGUsIHdlIHN5c3RlbWF0aWNhbGx5IGFkZHJlc3NlZCBvdXRsaWVycyBpbiBtdWx0aXBsZSBjb2x1bW5zIG9mIG91ciBkYXRhc2V0LiBCZWdpbm5pbmcgd2l0aCBhIHN1bW1hcnkgb2YgZWFjaCBjb2x1bW4ncyBzdGF0aXN0aWNzLCBpbmNsdWRpbmcgcXVhcnRpbGVzIGFuZCB0aGUgaW50ZXJxdWFydGlsZSByYW5nZSAoSVFSKSwgd2UgZXN0YWJsaXNoZWQgb3V0bGllciBkZXRlY3Rpb24gbGltaXRzLiBBIHZpc3VhbCBhc3Nlc3NtZW50IHdhcyBjb25kdWN0ZWQgdXNpbmcgYm94cGxvdHMsIGNhdGVnb3JpemVkIGJ5IHJlbGV2YW50IHZhcmlhYmxlcyBzdWNoIGFzICJQb3RhYmlsaXR5LiIgQSBsb29wIHdhcyBpbXBsZW1lbnRlZCB0byBpdGVyYXRpdmVseSBpZGVudGlmeSBhbmQgcmVtb3ZlIG91dGxpZXJzIGluIGVhY2ggY29sdW1uLCBlbnN1cmluZyBhIHJvYnVzdCBjbGVhbnNpbmcgcHJvY2Vzcy4gVGhlIGZpbmFsIHN0ZXAgaW52b2x2ZWQgc3VtbWFyaXppbmcgdGhlIGNvbHVtbnMgcG9zdC1vdXRsaWVyIHJlbW92YWwsIG9mZmVyaW5nIGluc2lnaHRzIGludG8gdGhlIGltcGFjdCBvbiB0aGUgZGlzdHJpYnV0aW9uIG9mIGVhY2ggdmFyaWFibGUuIFRoaXMgY29tcHJlaGVuc2l2ZSBhcHByb2FjaCB3YXMgYXBwbGllZCB1bmlmb3JtbHkgdG8gYWxsIGRhdGFzZXQgY29sdW1ucywgcHJvbW90aW5nIGNvbnNpc3RlbmN5IGluIHRoZSBvdXRsaWVyLWhhbmRsaW5nwqBwcm9jZXNzLgoKIyMgRXZhbHVhdGlvbiBhbmQgQ29tcGFyaXNvbgoKIyMjIEluZm9ybWF0aW9uIGdhaW4gKElEMykKCkluIHRoaXMgUiBjb2RlLCB0aGUgZGF0YXNldCB1bmRlcmdvZXMgYSBwcm9jZXNzIG9mIHRyYWluaW5nIGFuZCB0ZXN0aW5nIHVzaW5nIHRoZSBJRDMgYWxnb3JpdGhtIGZvciBkZWNpc2lvbiB0cmVlIGNsYXNzaWZpY2F0aW9uLiBUaGUgZGF0YSBpcyBzdWNjZXNzaXZlbHkgc3BsaXQgaW50byB0cmFpbmluZyBzZXRzIG9mIDcwJSwgODAlLCBhbmQgOTAlLCB3aXRoIGNvcnJlc3BvbmRpbmcgdGVzdGluZyBzZXRzIG9mIDMwJSwgMjAlLCBhbmQgMTAlLiBUaGUgZGVjaXNpb24gdHJlZSBtb2RlbHMgYXJlIHRyYWluZWQgb24gdGhlc2Ugc3Vic2V0cywgdXRpbGl6aW5nIGZlYXR1cmVzIHN1Y2ggYXMgcEgsIGhhcmRuZXNzLCBzb2xpZHMsIGNobG9yYW1pbmVzLCBzdWxmYXRlLCBjb25kdWN0aXZpdHksIG9yZ2FuaWMgY2FyYm9uLCB0cmloYWxvbWV0aGFuZXMsIGFuZCB0dXJiaWRpdHkgdG8gcHJlZGljdCB3YXRlciBwb3RhYmlsaXR5LgoKRm9yIGVhY2ggc3BsaXQsIHRoZSBkZWNpc2lvbiB0cmVlIG1vZGVscyBhcmUgZXZhbHVhdGVkIG9uIHRoZWlyIHJlc3BlY3RpdmUgdGVzdGluZyBzZXRzLCBhbmQgcGVyZm9ybWFuY2UgbWV0cmljcyBzdWNoIGFzIGNvbmZ1c2lvbiBtYXRyaWNlcyBhbmQgYWNjdXJhY3kgYXJlIGNvbXB1dGVkLiBBZGRpdGlvbmFsbHksIFJlY2VpdmVyIE9wZXJhdGluZyBDaGFyYWN0ZXJpc3RpYyAoUk9DKSBjdXJ2ZXMgYXJlIGdlbmVyYXRlZCwgcHJvdmlkaW5nIGluc2lnaHRzIGludG8gdGhlIG1vZGVscycgZGlzY3JpbWluYXRpb24gY2FwYWJpbGl0aWVzLiBUaGUgQXJlYSBVbmRlciB0aGUgQ3VydmUgKEFVQykgaXMgY2FsY3VsYXRlZCBhcyBhIHF1YW50aXRhdGl2ZSBtZWFzdXJlIG9mIG1vZGVsIHBlcmZvcm1hbmNlLiBUaGlzIGNvbXByZWhlbnNpdmUgYXBwcm9hY2ggZW5hYmxlcyBhIHN5c3RlbWF0aWMgZXhwbG9yYXRpb24gb2YgdGhlIElEMyBkZWNpc2lvbiB0cmVlJ3MgZWZmZWN0aXZlbmVzcyBpbiBwcmVkaWN0aW5nIHdhdGVyIHBvdGFiaWxpdHkgdW5kZXIgdmFyeWluZyB0cmFpbmluZyBhbmQgdGVzdGluZ8Kgc2NlbmFyaW9zLgoKU3BsaXR0aW5nIHRoZSBkYXRhIHNldCBpbnRvIHR3byBzdWJzZXRzOiBUcmFpbmluZyg3MCUpIGFuZCBUZXN0aW5nKDMwJSk6CgpgYGB7cn0Kc2V0LnNlZWQoMTk1OCkKaW5kIDwtIHNhbXBsZSgyLCBucm93KHdwKSwgcmVwbGFjZSA9IFRSVUUsIHByb2IgPSBjKDAuNywgMC4zKSkKdHJhaW4uZGF0YSA8LSB3cFtpbmQgPT0gMSwgXQp0ZXN0LmRhdGEgPC0gd3BbaW5kID09IDIsIF0KdHJhaW4uZGF0YSRQb3RhYmlsaXR5IDwtIGFzLmZhY3Rvcih0cmFpbi5kYXRhJFBvdGFiaWxpdHkpCnRlc3QuZGF0YSRQb3RhYmlsaXR5IDwtIGFzLmZhY3Rvcih0ZXN0LmRhdGEkUG90YWJpbGl0eSkKCgpteUZvcm11bGEgPC0gUG90YWJpbGl0eSB+IHBoK0hhcmRuZXNzK1NvbGlkcytDaGxvcmFtaW5lcytTdWxmYXRlK0NvbmR1Y3Rpdml0eStPcmdhbmljX2NhcmJvbitUcmloYWxvbWV0aGFuZXMrVHVyYmlkaXR5CiNteUZvcm11bGEgPC0gUG90YWJpbGl0eSB+IHBoK0hhcmRuZXNzK1NvbGlkcytDaGxvcmFtaW5lcytTdWxmYXRlCgoKbS5jdHJlZSA8LSBjdHJlZShteUZvcm11bGEsIGRhdGEgPSB0cmFpbi5kYXRhKQp0YWJsZShwcmVkaWN0KG0uY3RyZWUpLCB0cmFpbi5kYXRhJFBvdGFiaWxpdHkpCgpwcmludChtLmN0cmVlKQpwbG90KG0uY3RyZWUsIHR5cGU9InNpbXBsZSIpCnBsb3QobS5jdHJlZSkKCgp0ZXN0UHJlZCA8LSBwcmVkaWN0KG0uY3RyZWUsIG5ld2RhdGEgPSB0ZXN0LmRhdGEpCnJlc3VsdDwtdGFibGUodGVzdFByZWQsIHRlc3QuZGF0YSRQb3RhYmlsaXR5KQoKCmNvX3Jlc3VsdCA8LSBjb25mdXNpb25NYXRyaXgocmVzdWx0KQpwcmludChjb19yZXN1bHQpCmFzLm1hdHJpeChjb19yZXN1bHQsIHdoYXQgPSAiY2xhc3NlcyIpCmFjYyA8LSBjb19yZXN1bHQkb3ZlcmFsbFsiQWNjdXJhY3kiXQphY2MqMTAwCgoKcHJlZF9wcm9icyA8LSBhcy5udW1lcmljKHByZWRpY3QobS5jdHJlZSwgbmV3ZGF0YSA9IHRlc3QuZGF0YSwgdHlwZSA9ICJyZXNwb25zZSIpKQpiaW5hcnlfb3V0Y29tZSA8LSBhcy5udW1lcmljKHRlc3QuZGF0YSRQb3RhYmlsaXR5ID09ICJQb3RhYmxlIikKIyBST0MgY3VydmUKcm9jX2N1cnZlIDwtIHJvYyhiaW5hcnlfb3V0Y29tZSwgcHJlZF9wcm9icykKcGxvdChyb2NfY3VydmUsIG1haW4gPSAiUk9DIEN1cnZlIiwgY29sID0gImJsdWUiLCBsd2QgPSAyKQphYmxpbmUoYSA9IDAsIGIgPSAxLCBjb2wgPSAiZ3JheSIsIGx0eSA9IDIpCiMgUHJpbnQgQVVDCmNhdCgiQVVDOiIsIGF1Yyhyb2NfY3VydmUpLCAiXG4iKQpgYGAKClNwbGl0dGluZyB0aGUgZGF0YSBzZXQgaW50byB0d28gc3Vic2V0czogVHJhaW5pbmcoODAlKSBhbmQgVGVzdGluZygyMCUpOgoKYGBge3J9CgpzZXQuc2VlZCgxOTU4KQppbmQgPC0gc2FtcGxlKDIsIG5yb3cod3ApLCByZXBsYWNlID0gVFJVRSwgcHJvYiA9IGMoMC44LCAwLjIpKQp0cmFpbi5kYXRhIDwtIHdwW2luZCA9PSAxLCBdCnRlc3QuZGF0YSA8LSB3cFtpbmQgPT0gMiwgXQp0cmFpbi5kYXRhJFBvdGFiaWxpdHkgPC0gYXMuZmFjdG9yKHRyYWluLmRhdGEkUG90YWJpbGl0eSkKCm15Rm9ybXVsYSA8LSBQb3RhYmlsaXR5IH4gcGgrSGFyZG5lc3MrU29saWRzK0NobG9yYW1pbmVzK1N1bGZhdGUrQ29uZHVjdGl2aXR5K09yZ2FuaWNfY2FyYm9uK1RyaWhhbG9tZXRoYW5lcytUdXJiaWRpdHkKI215Rm9ybXVsYSA8LSBQb3RhYmlsaXR5IH4gcGgrSGFyZG5lc3MrU29saWRzK0NobG9yYW1pbmVzK1N1bGZhdGUKCgptLmN0cmVlIDwtIGN0cmVlKG15Rm9ybXVsYSwgZGF0YSA9IHRyYWluLmRhdGEpCnRhYmxlKHByZWRpY3QobS5jdHJlZSksIHRyYWluLmRhdGEkUG90YWJpbGl0eSkKCnByaW50KG0uY3RyZWUpCnBsb3QobS5jdHJlZSwgdHlwZT0ic2ltcGxlIikKcGxvdChtLmN0cmVlKQoKdGVzdFByZWQgPC0gcHJlZGljdChtLmN0cmVlLCBuZXdkYXRhID0gdGVzdC5kYXRhKQpyZXN1bHQ8LXRhYmxlKHRlc3RQcmVkLCB0ZXN0LmRhdGEkUG90YWJpbGl0eSkKCgpjb19yZXN1bHQgPC0gY29uZnVzaW9uTWF0cml4KHJlc3VsdCkKcHJpbnQoY29fcmVzdWx0KQphcy5tYXRyaXgoY29fcmVzdWx0LCB3aGF0ID0gImNsYXNzZXMiKQphY2MgPC0gY29fcmVzdWx0JG92ZXJhbGxbIkFjY3VyYWN5Il0KYWNjKjEwMAoKcHJlZF9wcm9icyA8LSBhcy5udW1lcmljKHByZWRpY3QobS5jdHJlZSwgbmV3ZGF0YSA9IHRlc3QuZGF0YSwgdHlwZSA9ICJyZXNwb25zZSIpKQpiaW5hcnlfb3V0Y29tZSA8LSBhcy5udW1lcmljKHRlc3QuZGF0YSRQb3RhYmlsaXR5ID09ICJQb3RhYmxlIikKIyBST0MgY3VydmUKcm9jX2N1cnZlIDwtIHJvYyhiaW5hcnlfb3V0Y29tZSwgcHJlZF9wcm9icykKcGxvdChyb2NfY3VydmUsIG1haW4gPSAiUk9DIEN1cnZlIiwgY29sID0gImJsdWUiLCBsd2QgPSAyKQphYmxpbmUoYSA9IDAsIGIgPSAxLCBjb2wgPSAiZ3JheSIsIGx0eSA9IDIpCiMgUHJpbnQgQVVDCmNhdCgiQVVDOiIsIGF1Yyhyb2NfY3VydmUpLCAiXG4iKQpgYGAKClNwbGl0dGluZyB0aGUgZGF0YSBzZXQgaW50byB0d28gc3Vic2V0czogVHJhaW5pbmcoOTAlKSBhbmQgVGVzdGluZygxMCUpOgoKYGBge3J9CnNldC5zZWVkKDE5NTgpCmluZCA8LSBzYW1wbGUoMiwgbnJvdyh3cCksIHJlcGxhY2UgPSBUUlVFLCBwcm9iID0gYygwLjksIDAuMSkpCnRyYWluLmRhdGEgPC0gd3BbaW5kID09IDEsIF0KdGVzdC5kYXRhIDwtIHdwW2luZCA9PSAyLCBdCnRyYWluLmRhdGEkUG90YWJpbGl0eSA8LSBhcy5mYWN0b3IodHJhaW4uZGF0YSRQb3RhYmlsaXR5KQoKbXlGb3JtdWxhIDwtIFBvdGFiaWxpdHkgfiBwaCtIYXJkbmVzcytTb2xpZHMrQ2hsb3JhbWluZXMrU3VsZmF0ZStDb25kdWN0aXZpdHkrT3JnYW5pY19jYXJib24rVHJpaGFsb21ldGhhbmVzK1R1cmJpZGl0eQojbXlGb3JtdWxhIDwtIFBvdGFiaWxpdHkgfiBwaCtIYXJkbmVzcytTb2xpZHMrQ2hsb3JhbWluZXMrU3VsZmF0ZQoKCm0uY3RyZWUgPC0gY3RyZWUobXlGb3JtdWxhLCBkYXRhID0gdHJhaW4uZGF0YSkKdGFibGUocHJlZGljdChtLmN0cmVlKSwgdHJhaW4uZGF0YSRQb3RhYmlsaXR5KQoKcHJpbnQobS5jdHJlZSkKcGxvdChtLmN0cmVlLCB0eXBlPSJzaW1wbGUiKQpwbG90KG0uY3RyZWUpCgp0ZXN0UHJlZCA8LSBwcmVkaWN0KG0uY3RyZWUsIG5ld2RhdGEgPSB0ZXN0LmRhdGEpCnJlc3VsdDwtdGFibGUodGVzdFByZWQsIHRlc3QuZGF0YSRQb3RhYmlsaXR5KQoKCmNvX3Jlc3VsdCA8LSBjb25mdXNpb25NYXRyaXgocmVzdWx0KQpwcmludChjb19yZXN1bHQpCmFzLm1hdHJpeChjb19yZXN1bHQsIHdoYXQgPSAiY2xhc3NlcyIpCmFjYyA8LSBjb19yZXN1bHQkb3ZlcmFsbFsiQWNjdXJhY3kiXQphY2MqMTAwCgpwcmVkX3Byb2JzIDwtIGFzLm51bWVyaWMocHJlZGljdChtLmN0cmVlLCBuZXdkYXRhID0gdGVzdC5kYXRhLCB0eXBlID0gInJlc3BvbnNlIikpCmJpbmFyeV9vdXRjb21lIDwtIGFzLm51bWVyaWModGVzdC5kYXRhJFBvdGFiaWxpdHkgPT0gIlBvdGFibGUiKQojIFJPQyBjdXJ2ZQpyb2NfY3VydmUgPC0gcm9jKGJpbmFyeV9vdXRjb21lLCBwcmVkX3Byb2JzKQpwbG90KHJvY19jdXJ2ZSwgbWFpbiA9ICJST0MgQ3VydmUiLCBjb2wgPSAiYmx1ZSIsIGx3ZCA9IDIpCmFibGluZShhID0gMCwgYiA9IDEsIGNvbCA9ICJncmF5IiwgbHR5ID0gMikKIyBQcmludCBBVUMKY2F0KCJBVUM6IiwgYXVjKHJvY19jdXJ2ZSksICJcbiIpCmBgYAoKIyMjIEdhaW4gcmF0aW8gKEM0LjUpCgphIGRlY2lzaW9uIHRyZWUtYmFzZWQgY2xhc3NpZmllciwgaXMgdXRpbGl6ZWQgZm9yIG1vZGVsIHRyYWluaW5nIGFuZCBldmFsdWF0aW9uLiBUaGUgZGF0YXNldCB1bmRlcmdvZXMgY3Jvc3MtdmFsaWRhdGlvbiB3aXRoIGRpZmZlcmVudCBmb2xkIHNldHRpbmdzICgzIGZvbGRzLCA1IGZvbGRzLCBhbmQgMTAgZm9sZHMpLiBGb3IgZWFjaCBmb2xkIGNvbmZpZ3VyYXRpb24sIGEgSjQ4IG1vZGVsIGlzIHRyYWluZWQsIGFuZCBpdHMgcHJlZGljdGl2ZSBwZXJmb3JtYW5jZSBpcyBhc3Nlc3NlZCB1c2luZyBSZWNlaXZlciBPcGVyYXRpbmcgQ2hhcmFjdGVyaXN0aWMgKFJPQykgY3VydmVzLiBUaGUgQXJlYSBVbmRlciB0aGUgQ3VydmUgaXMgY2FsY3VsYXRlZCBmb3IgZWFjaCBST0MgY3VydmUsIHByb3ZpZGluZyBhIHF1YW50aXRhdGl2ZSBtZWFzdXJlIG9mIHRoZSBtb2RlbCdzIGFiaWxpdHkgdG8gcHJlZGljdCB3YXRlciBwb3RhYmlsaXR5LiBOb3RhYmx5LCB0aGUgdmlzdWFsIGluc3BlY3Rpb24gb2YgdGhlIFJPQyBjdXJ2ZXMgaW5kaWNhdGVzIHRoYXQgdGhlIG1vZGVsIHRyYWluZWQgd2l0aCAxMC1mb2xkIGNyb3NzLXZhbGlkYXRpb24gZXhoaWJpdHMgdGhlIGhpZ2hlc3QgZGlzY3JpbWluYXRpdmUgcGVyZm9ybWFuY2UuIFRoaXMgY29tcGFyYXRpdmUgYW5hbHlzaXMgYWNyb3NzIHZhcmlvdXMgY3Jvc3MtdmFsaWRhdGlvbiBzY2VuYXJpb3Mgb2ZmZXJzIHZhbHVhYmxlIGluc2lnaHRzIGludG8gdGhlIHJvYnVzdG5lc3MgYW5kIGdlbmVyYWxpemF0aW9uwqBjYXBhYmlsaXR5LgoKYGBge3J9CiMgMyBmb2xkcwpzZXQuc2VlZCgxOTU4KQp0cmFpbiA8LSBjcmVhdGVGb2xkcyh3cCRQb3RhYmlsaXR5LCBrPTMpCkM0NUZpdCA8LSB0cmFpbihQb3RhYmlsaXR5IH4gLixtZXRob2QgPSAiSjQ4IixkYXRhID0gd3AsCiAgICAgICAgICAgICAgICB0ckNvbnRyb2wgPSB0cmFpbkNvbnRyb2woCiAgICAgICAgICAgICAgICBtZXRob2QgPSAiY3YiLAogICAgICAgICAgICAgICAgaW5kZXggPSB0cmFpbiwKICAgICAgICAgICAgICAgIHNhdmVQcmVkaWN0aW9ucyA9IFRSVUUpKQoKQzQ1Rml0CnN1bW1hcnkoQzQ1Rml0KQoKQzQ1Rml0JGZpbmFsTW9kZWwKCnByZWRfcHJvYnMgPC0gcHJlZGljdChDNDVGaXQsIG5ld2RhdGEgPSB3cCkKcmUzPC10YWJsZShwcmVkX3Byb2JzICx3cCRQb3RhYmlsaXR5KQoKcjMgPC0gY29uZnVzaW9uTWF0cml4KHJlMykKYWNjIDwtIHIzJG92ZXJhbGxbIkFjY3VyYWN5Il0qMTAwCmFjYwphcy5tYXRyaXgocjMsIHdoYXQgPSAiY2xhc3NlcyIpCnByaW50KHIzKQoKcHJlZF9wcm9icyA8LSBwcmVkaWN0KEM0NUZpdCwgbmV3ZGF0YSA9IHdwLCB0eXBlID0gInByb2IiKVssICJQb3RhYmxlIl0KYmluYXJ5X291dGNvbWUgPC0gYXMubnVtZXJpYyh3cCRQb3RhYmlsaXR5ID09ICJQb3RhYmxlIikKIyBST0MgY3VydmUKcm9jX2N1cnZlIDwtIHJvYyhiaW5hcnlfb3V0Y29tZSwgcHJlZF9wcm9icykKcGxvdChyb2NfY3VydmUsIG1haW4gPSAiUk9DIEN1cnZlIiwgY29sID0gImJsdWUiLCBsd2QgPSAyKQphYmxpbmUoYSA9IDAsIGIgPSAxLCBjb2wgPSAiZ3JheSIsIGx0eSA9IDIpCiMgUHJpbnQgQVVDCmNhdCgiQVVDOiIsIGF1Yyhyb2NfY3VydmUpLCAiXG4iKQpgYGAKCmBgYHtyfQojIDUgZm9sZHMKc2V0LnNlZWQoMTk1OCkKdHJhaW4gPC0gY3JlYXRlRm9sZHMod3AkUG90YWJpbGl0eSwgaz01KQpDNDVGaXQgPC0gdHJhaW4oUG90YWJpbGl0eSB+LiwgbWV0aG9kPSJKNDgiLCBkYXRhPXdwLAogICAgICAgICAgICAgICAgdHJDb250cm9sID0gdHJhaW5Db250cm9sKAogICAgICAgICAgICAgICAgbWV0aG9kID0iY3YiLCAKICAgICAgICAgICAgICAgIGluZGV4ID0gdHJhaW4sCiAgICAgICAgICAgICAgICBzYXZlUHJlZGljdGlvbnMgPSBUUlVFKSkKCkM0NUZpdApzdW1tYXJ5KEM0NUZpdCkKCkM0NUZpdCRmaW5hbE1vZGVsCgpwcmVkX3Byb2JzIDwtIHByZWRpY3QoQzQ1Rml0LCBuZXdkYXRhID0gd3ApCnJlNTwtdGFibGUocHJlZF9wcm9icyAsd3AkUG90YWJpbGl0eSkKCnI1IDwtIGNvbmZ1c2lvbk1hdHJpeChyZTUpCmFjYyA8LSByNSRvdmVyYWxsWyJBY2N1cmFjeSJdKjEwMAphY2MKYXMubWF0cml4KHI1LCB3aGF0ID0gImNsYXNzZXMiKQpwcmludChyNSkKCnByZWRfcHJvYnMgPC0gcHJlZGljdChDNDVGaXQsIG5ld2RhdGEgPSB3cCwgdHlwZSA9ICJwcm9iIilbLCAiUG90YWJsZSJdCmJpbmFyeV9vdXRjb21lIDwtIGFzLm51bWVyaWMod3AkUG90YWJpbGl0eSA9PSAiUG90YWJsZSIpCiMgUk9DIGN1cnZlCnJvY19jdXJ2ZSA8LSByb2MoYmluYXJ5X291dGNvbWUsIHByZWRfcHJvYnMpCnBsb3Qocm9jX2N1cnZlLCBtYWluID0gIlJPQyBDdXJ2ZSIsIGNvbCA9ICJibHVlIiwgbHdkID0gMikKYWJsaW5lKGEgPSAwLCBiID0gMSwgY29sID0gImdyYXkiLCBsdHkgPSAyKQojIFByaW50IEFVQwpjYXQoIkFVQzoiLCBhdWMocm9jX2N1cnZlKSwgIlxuIikKCgpgYGAKCmBgYHtyfQojIDEwIGZvbGRzCnNldC5zZWVkKDE5NTgpCgp0cmFpbiA8LSBjcmVhdGVGb2xkcyh3cCRQb3RhYmlsaXR5LCBrPTEwKQpDNDVGaXQgPC0gdHJhaW4oUG90YWJpbGl0eSB+LiwgbWV0aG9kPSJKNDgiLCBkYXRhPXdwLAogICAgICAgICAgICAgICAgdHJDb250cm9sID0gdHJhaW5Db250cm9sKAogICAgICAgICAgICAgICAgICBtZXRob2Q9ImN2IiwgaW5kZXhPdXQ9dHJhaW4pKQoKQzQ1Rml0CnN1bW1hcnkoQzQ1Rml0KQoKQzQ1Rml0JGZpbmFsTW9kZWwKCnByZWRfcHJvYnMgPC0gcHJlZGljdChDNDVGaXQsIG5ld2RhdGEgPSB3cCkKcmU8LXRhYmxlKHByZWRfcHJvYnMgLHdwJFBvdGFiaWxpdHkpCgpyIDwtIGNvbmZ1c2lvbk1hdHJpeChyZSkKYWNjIDwtIHIkb3ZlcmFsbFsiQWNjdXJhY3kiXSoxMDAKYWNjCmFzLm1hdHJpeChyLCB3aGF0ID0gImNsYXNzZXMiKQpwcmludChyKQoKcHJlZF9wcm9icyA8LSBwcmVkaWN0KEM0NUZpdCwgbmV3ZGF0YSA9IHdwLCB0eXBlID0gInByb2IiKVssICJQb3RhYmxlIl0KYmluYXJ5X291dGNvbWUgPC0gYXMubnVtZXJpYyh3cCRQb3RhYmlsaXR5ID09ICJQb3RhYmxlIikKIyBST0MgY3VydmUKcm9jX2N1cnZlIDwtIHJvYyhiaW5hcnlfb3V0Y29tZSwgcHJlZF9wcm9icykKcGxvdChyb2NfY3VydmUsIG1haW4gPSAiUk9DIEN1cnZlIiwgY29sID0gImJsdWUiLCBsd2QgPSAyKQphYmxpbmUoYSA9IDAsIGIgPSAxLCBjb2wgPSAiZ3JheSIsIGx0eSA9IDIpCiMgUHJpbnQgQVVDCmNhdCgiQVVDOiIsIGF1Yyhyb2NfY3VydmUpLCAiXG4iKQoKYGBgCgpDNS4wIG5ld2VyIHZlcnNpb24gb2YgQzQuNSBTcGxpdHRpbmcgdGhlIGRhdGEgc2V0IGludG8gdHdvIHN1YnNldHM6IFRyYWluaW5nKDcwJSkgYW5kIFRlc3RpbmcoMzAlKToKCmBgYHtyfQpzZXQuc2VlZCgxOTU4KQp0cmFpbi5pbmRpY2VzIDwtIHNhbXBsZSgyLCBucm93KHdhdGVyX3BvdGFiaWxpdHkpLCByZXBsYWNlPVRSVUUsIHByb2I9YygwLjcsIDAuMykpCncudHJhaW4gPC0gd2F0ZXJfcG90YWJpbGl0eVt0cmFpbi5pbmRpY2VzID09IDEsIF0Kdy50ZXN0IDwtIHdhdGVyX3BvdGFiaWxpdHlbdHJhaW4uaW5kaWNlcyA9PSAyLCBdCncudHJhaW4kUG90YWJpbGl0eSA8LSBhcy5mYWN0b3Iody50cmFpbiRQb3RhYmlsaXR5KQoKbW9kZWwgPC0gQzUuMChQb3RhYmlsaXR5IH4uLCBkYXRhPXcudHJhaW4pCgpyZXN1bHRzIDwtIHByZWRpY3Qob2JqZWN0PW1vZGVsLCBuZXdkYXRhPXcudGVzdCwgdHlwZT0iY2xhc3MiKQoKdGFibGUocmVzdWx0cywgdy50ZXN0JFBvdGFiaWxpdHkpCgpwbG90KG1vZGVsKQpwbG90KG1vZGVsLHR5cGU9J3NpbXBsZScpCgpyIDwtIGNvbmZ1c2lvbk1hdHJpeChyZXN1bHRzLCB3LnRlc3QkUG90YWJpbGl0eSkKYWNjIDwtIHIkb3ZlcmFsbFsiQWNjdXJhY3kiXSoxMDAKYWNjCmFzLm1hdHJpeChyLCB3aGF0ID0gImNsYXNzZXMiKQpwcmludChyKQoKCgpwcmVkX3Byb2JzIDwtIHByZWRpY3QobW9kZWwsIG5ld2RhdGEgPSB3LnRlc3QsIHR5cGUgPSAicHJvYiIpWywgIlBvdGFibGUiXQpiaW5hcnlfb3V0Y29tZSA8LSBhcy5udW1lcmljKHcudGVzdCRQb3RhYmlsaXR5ID09ICJQb3RhYmxlIikKIyBST0MgY3VydmUKcm9jX2N1cnZlIDwtIHJvYyhiaW5hcnlfb3V0Y29tZSwgcHJlZF9wcm9icykKcGxvdChyb2NfY3VydmUsIG1haW4gPSAiUk9DIEN1cnZlIiwgY29sID0gImJsdWUiLCBsd2QgPSAyKQphYmxpbmUoYSA9IDAsIGIgPSAxLCBjb2wgPSAiZ3JheSIsIGx0eSA9IDIpCiMgUHJpbnQgQVVDCmNhdCgiQVVDOiIsIGF1Yyhyb2NfY3VydmUpLCAiXG4iKQpgYGAKClNwbGl0dGluZyB0aGUgZGF0YSBzZXQgaW50byB0d28gc3Vic2V0czogVHJhaW5pbmcoODAlKSBhbmQgVGVzdGluZygyMCUpOgoKYGBge3J9CnNldC5zZWVkKDE5NTgpCnRyYWluLmluZGljZXMgPC0gc2FtcGxlKDIsIG5yb3cod2F0ZXJfcG90YWJpbGl0eSksIHJlcGxhY2U9VFJVRSwgcHJvYj1jKDAuOCwgMC4yKSkKdy50cmFpbiA8LSB3YXRlcl9wb3RhYmlsaXR5W3RyYWluLmluZGljZXMgPT0gMSwgXQp3LnRlc3QgPC0gd2F0ZXJfcG90YWJpbGl0eVt0cmFpbi5pbmRpY2VzID09IDIsIF0Kdy50cmFpbiRQb3RhYmlsaXR5IDwtIGFzLmZhY3Rvcih3LnRyYWluJFBvdGFiaWxpdHkpCgoKbW9kZWwgPC0gQzUuMChQb3RhYmlsaXR5IH4uLCBkYXRhPXcudHJhaW4pCgpyZXN1bHRzIDwtIHByZWRpY3Qob2JqZWN0PW1vZGVsLCBuZXdkYXRhPXcudGVzdCwgdHlwZT0iY2xhc3MiKQoKdGFibGUocmVzdWx0cywgdy50ZXN0JFBvdGFiaWxpdHkpCgpwbG90KG1vZGVsKQpwbG90KG1vZGVsLHR5cGU9J3NpbXBsZScpCgpyIDwtIGNvbmZ1c2lvbk1hdHJpeChyZXN1bHRzLCB3LnRlc3QkUG90YWJpbGl0eSkKYWNjIDwtIHIkb3ZlcmFsbFsiQWNjdXJhY3kiXSoxMDAKYWNjCmFzLm1hdHJpeChyLCB3aGF0ID0gImNsYXNzZXMiKQpwcmludChyKQoKCnByZWRfcHJvYnMgPC0gcHJlZGljdChtb2RlbCwgbmV3ZGF0YSA9IHcudGVzdCwgdHlwZSA9ICJwcm9iIilbLCAiUG90YWJsZSJdCmJpbmFyeV9vdXRjb21lIDwtIGFzLm51bWVyaWMody50ZXN0JFBvdGFiaWxpdHkgPT0gIlBvdGFibGUiKQojIFJPQyBjdXJ2ZQpyb2NfY3VydmUgPC0gcm9jKGJpbmFyeV9vdXRjb21lLCBwcmVkX3Byb2JzKQpwbG90KHJvY19jdXJ2ZSwgbWFpbiA9ICJST0MgQ3VydmUiLCBjb2wgPSAiYmx1ZSIsIGx3ZCA9IDIpCmFibGluZShhID0gMCwgYiA9IDEsIGNvbCA9ICJncmF5IiwgbHR5ID0gMikKIyBQcmludCBBVUMKY2F0KCJBVUM6IiwgYXVjKHJvY19jdXJ2ZSksICJcbiIpCmBgYAoKU3BsaXR0aW5nIHRoZSBkYXRhIHNldCBpbnRvIHR3byBzdWJzZXRzOiBUcmFpbmluZyg5MCUpIGFuZCBUZXN0aW5nKDEwJSk6CgpgYGB7cn0Kc2V0LnNlZWQoMTk1OCkKdHJhaW4uaW5kaWNlcyA8LSBzYW1wbGUoMiwgbnJvdyh3YXRlcl9wb3RhYmlsaXR5KSwgcmVwbGFjZT1UUlVFLCBwcm9iPWMoMC45LCAwLjEpKQp3LnRyYWluIDwtIHdhdGVyX3BvdGFiaWxpdHlbdHJhaW4uaW5kaWNlcyA9PSAxLCBdCncudGVzdCA8LSB3YXRlcl9wb3RhYmlsaXR5W3RyYWluLmluZGljZXMgPT0gMiwgXQp3LnRyYWluJFBvdGFiaWxpdHkgPC0gYXMuZmFjdG9yKHcudHJhaW4kUG90YWJpbGl0eSkKCgptb2RlbCA8LSBDNS4wKFBvdGFiaWxpdHkgfi4sIGRhdGE9dy50cmFpbikKCnJlc3VsdHMgPC0gcHJlZGljdChvYmplY3Q9bW9kZWwsIG5ld2RhdGE9dy50ZXN0LCB0eXBlPSJjbGFzcyIpCgp0YWJsZShyZXN1bHRzLCB3LnRlc3QkUG90YWJpbGl0eSkKCnBsb3QobW9kZWwpCnBsb3QobW9kZWwsdHlwZT0nc2ltcGxlJykKCnIgPC0gY29uZnVzaW9uTWF0cml4KHJlc3VsdHMsIHcudGVzdCRQb3RhYmlsaXR5KQphY2MgPC0gciRvdmVyYWxsWyJBY2N1cmFjeSJdKjEwMAphY2MKYXMubWF0cml4KHIsIHdoYXQgPSAiY2xhc3NlcyIpCnByaW50KHIpCgoKCnByZWRfcHJvYnMgPC0gcHJlZGljdChtb2RlbCwgbmV3ZGF0YSA9IHcudGVzdCwgdHlwZSA9ICJwcm9iIilbLCAiUG90YWJsZSJdCmJpbmFyeV9vdXRjb21lIDwtIGFzLm51bWVyaWMody50ZXN0JFBvdGFiaWxpdHkgPT0gIlBvdGFibGUiKQojIFJPQyBjdXJ2ZQpyb2NfY3VydmUgPC0gcm9jKGJpbmFyeV9vdXRjb21lLCBwcmVkX3Byb2JzKQpwbG90KHJvY19jdXJ2ZSwgbWFpbiA9ICJST0MgQ3VydmUiLCBjb2wgPSAiYmx1ZSIsIGx3ZCA9IDIpCmFibGluZShhID0gMCwgYiA9IDEsIGNvbCA9ICJncmF5IiwgbHR5ID0gMikKIyBQcmludCBBVUMKY2F0KCJBVUM6IiwgYXVjKHJvY19jdXJ2ZSksICJcbiIpCmBgYAoKIyMjIFRvIGltcHJvdmUgdGhlIHJlYWRhYmlsaXR5IG9mIHRoZSBkZWNpc2lvbiB0cmVlLCB3ZSBkZWNpZGVkIHRvIHNhbXBsZSB0aGUgZGF0YSB1c2luZyBvbmx5IHRoZSBwSCBhbmQgc3VsZmF0ZSBhdHRyaWJ1dGVzLiBXZSB0aGVuIHNwbGl0IHRoZSBkYXRhIGludG8gdHJhaW5pbmcgYW5kIHRlc3Rpbmcgc2V0cyB1c2luZyB0aGUgc2FtZSBzcGxpdCBwb2ludHM6IFRyYWluaW5nKDkwJSkgYW5kIFRlc3RpbmcoMTAlKSwgd2hpY2ggYWxsb3dlZCBmb3IgYSBtb3JlIG1hbmFnZWFibGUgZGVjaXNpb24gdHJlZToKCmBgYHtyfQpzZXQuc2VlZCgxOTU4KQppbXBvcnRlbnRfZmVhdHVyZV9zYW1wbGUgPC0gc2VsZWN0KHdhdGVyX3BvdGFiaWxpdHksYygxLDUsMTApKQp0cmFpbi5pbmRpY2VzIDwtIHNhbXBsZSgyLCBucm93KGltcG9ydGVudF9mZWF0dXJlX3NhbXBsZSksIHJlcGxhY2U9VFJVRSwgcHJvYj1jKDAuOSwgMC4xKSkKdy50cmFpbiA8LSBpbXBvcnRlbnRfZmVhdHVyZV9zYW1wbGVbdHJhaW4uaW5kaWNlcyA9PSAxLCBdCncudGVzdCA8LSBpbXBvcnRlbnRfZmVhdHVyZV9zYW1wbGVbdHJhaW4uaW5kaWNlcyA9PSAyLCBdCncudHJhaW4kUG90YWJpbGl0eSA8LSBhcy5mYWN0b3Iody50cmFpbiRQb3RhYmlsaXR5KQoKCm1vZGVsIDwtIEM1LjAoUG90YWJpbGl0eSB+LiwgZGF0YT13LnRyYWluKQoKcmVzdWx0cyA8LSBwcmVkaWN0KG9iamVjdD1tb2RlbCwgbmV3ZGF0YT13LnRlc3QsIHR5cGU9ImNsYXNzIikKCnRhYmxlKHJlc3VsdHMsIHcudGVzdCRQb3RhYmlsaXR5KQoKcGxvdChtb2RlbCkKcGxvdChtb2RlbCx0eXBlPSdzaW1wbGUnKQoKciA8LSBjb25mdXNpb25NYXRyaXgocmVzdWx0cywgdy50ZXN0JFBvdGFiaWxpdHkpCmFjYyA8LSByJG92ZXJhbGxbIkFjY3VyYWN5Il0qMTAwCmFjYwphcy5tYXRyaXgociwgd2hhdCA9ICJjbGFzc2VzIikKcHJpbnQocikKCgoKcHJlZF9wcm9icyA8LSBwcmVkaWN0KG1vZGVsLCBuZXdkYXRhID0gdy50ZXN0LCB0eXBlID0gInByb2IiKVssICJQb3RhYmxlIl0KYmluYXJ5X291dGNvbWUgPC0gYXMubnVtZXJpYyh3LnRlc3QkUG90YWJpbGl0eSA9PSAiUG90YWJsZSIpCiMgUk9DIGN1cnZlCnJvY19jdXJ2ZSA8LSByb2MoYmluYXJ5X291dGNvbWUsIHByZWRfcHJvYnMpCnBsb3Qocm9jX2N1cnZlLCBtYWluID0gIlJPQyBDdXJ2ZSIsIGNvbCA9ICJibHVlIiwgbHdkID0gMikKYWJsaW5lKGEgPSAwLCBiID0gMSwgY29sID0gImdyYXkiLCBsdHkgPSAyKQojIFByaW50IEFVQwpjYXQoIkFVQzoiLCBhdWMocm9jX2N1cnZlKSwgIlxuIikKYGBgCgp3ZSBlbXBsb3llZCB0aGUgQzUuMCBhbGdvcml0aG0sIGFuIGVuaGFuY2VkIHZlcnNpb24gb2YgdGhlIEM0LjUgZGVjaXNpb24gdHJlZSwgZm9yIG1vZGVsIHRyYWluaW5nIGFuZCBldmFsdWF0aW9uIGFjcm9zcyBkaWZmZXJlbnQgdHJhaW5pbmcgYW5kIHRlc3Rpbmcgc2V0IHNwbGl0cy4gVGhlIGRhdGFzZXQgdW5kZXJ3ZW50IHRocmVlIHNjZW5hcmlvczogVHJhaW5pbmcoNzAlKSBhbmQgVGVzdGluZygzMCUpLCBUcmFpbmluZyg4MCUpIGFuZCBUZXN0aW5nKDIwJSksIGFuZCBUcmFpbmluZyg5MCUpIGFuZCBUZXN0aW5nKDEwJSkuIEZvciBlYWNoIGNhc2UsIHRoZSBDNS4wIG1vZGVsIHdhcyB0cmFpbmVkIG9uIHRoZSBkZXNpZ25hdGVkIHRyYWluaW5nIGRhdGEsIGV2YWx1YXRlZCBvbiB0aGUgdGVzdGluZyBkYXRhLCBhbmQgaXRzIHBlcmZvcm1hbmNlIHdhcyBhc3Nlc3NlZCB0aHJvdWdoIGFjY3VyYWN5LCBjb25mdXNpb24gbWF0cml4LCBhbmQgUk9DIGN1cnZlIHdpdGggQXJlYSBVbmRlciB0aGUgQ3VydmUgKEFVQykuCgpVcG9uIGNvbXBhcmF0aXZlIGFuYWx5c2lzLCBpdCB3YXMgb2JzZXJ2ZWQgdGhhdCB0aGUgbW9kZWwgdHJhaW5lZCB3aXRoIGEgbGFyZ2VyIHByb3BvcnRpb24gb2YgZGF0YSAoVHJhaW5pbmcgOTAlLCBUZXN0aW5nIDEwJSkgZGVtb25zdHJhdGVkIHN1cGVyaW9yIHBlcmZvcm1hbmNlLCBhY2hpZXZpbmcgaGlnaGVyIGFjY3VyYWN5IGFuZCBhIG1vcmUgZGlzY3JpbWluYXRpdmUgUk9DIGN1cnZlLiBUaGlzIGV4cGxvcmF0aW9uIGFjcm9zcyBkaWZmZXJlbnQgdHJhaW5pbmcgYW5kIHRlc3Rpbmcgc3BsaXRzIHByb3ZpZGVzIHZhbHVhYmxlIGluc2lnaHRzIGludG8gdGhlIHJvYnVzdG5lc3MgYW5kIGdlbmVyYWxpemF0aW9uIGNhcGFiaWxpdHkgb2YgdGhlIEM1LjAgZGVjaXNpb24gdHJlZSBhbGdvcml0aG0gZm9yIHByZWRpY3Rpbmcgd2F0ZXLCoHBvdGFiaWxpdHkuCgojIyMgR2luaSBpbmRleCAoQ0FSVCkKClNwbGl0dGluZyB0aGUgZGF0YSBzZXQgaW50byB0d28gc3Vic2V0czogVHJhaW5pbmcoNzAlKSBhbmQgVGVzdGluZygzMCUpOgoKYGBge3J9CnNldC5zZWVkKDE5NTgpCnRyYWluID0gc2FtcGxlKDIsIG5yb3cod3ApLCByZXBsYWNlPVRSVUUsIHByb2I9YygwLjcsIDAuMykpCndwLnRyYWluPXdwW3RyYWluID09IDEsXQp3cC50ZXN0PXdwW3RyYWluID09IDIsXQoKCgpmaXQudHJlZSA9IHJwYXJ0KFBvdGFiaWxpdHkgfiAuLCBkYXRhPXdwLCBtZXRob2QgPSAiY2xhc3MiLCBjcD0wLjAwOCkKZml0LnRyZWUKCnJwYXJ0LnBsb3QoZml0LnRyZWUpCgpmaXQudHJlZSR2YXJpYWJsZS5pbXBvcnRhbmNlCgpwcmVkLnRyZWUgPSBwcmVkaWN0KGZpdC50cmVlLCB3cC50ZXN0LCB0eXBlID0gImNsYXNzIikKcmUgPC0gdGFibGUocHJlZC50cmVlLCB3cC50ZXN0JFBvdGFiaWxpdHkpCgpjb19yZSA8LSBjb25mdXNpb25NYXRyaXgocmUpCnByaW50KGNvX3JlKQphcy5tYXRyaXgoY29fcmUsIHdoYXQgPSAiY2xhc3NlcyIpCmFjYyA8LSBjb19yZSRvdmVyYWxsWyJBY2N1cmFjeSJdCmFjYyoxMDAKCnBsb3RjcChmaXQudHJlZSkKcHJpbnRjcChmaXQudHJlZSkKCiMgRXhwbGljaXRseSByZXF1ZXN0IHRoZSBsb3dlc3QgY3AgdmFsdWUKZml0LnRyZWUkY3B0YWJsZVt3aGljaC5taW4oZml0LnRyZWUkY3B0YWJsZVssInhlcnJvciJdKSwiQ1AiXQoKYmVzdGNwIDwtZml0LnRyZWUkY3B0YWJsZVt3aGljaC5taW4oZml0LnRyZWUkY3B0YWJsZVssInhlcnJvciJdKSwiQ1AiXQpwcnVuZWQudHJlZSA8LSBwcnVuZShmaXQudHJlZSwgY3AgPSBiZXN0Y3ApCnJwYXJ0LnBsb3QocHJ1bmVkLnRyZWUpCgpwcmVkLnBydW5lID0gcHJlZGljdChwcnVuZWQudHJlZSwgd3AudGVzdCwgdHlwZT0iY2xhc3MiKQoKcmUgPC0gdGFibGUocHJlZC5wcnVuZSwgd3AudGVzdCRQb3RhYmlsaXR5KQoKY29fcmUgPC0gY29uZnVzaW9uTWF0cml4KHJlKQpwcmludChjb19yZSkKYXMubWF0cml4KGNvX3JlLCB3aGF0ID0gImNsYXNzZXMiKQphY2MgPC0gY29fcmUkb3ZlcmFsbFsiQWNjdXJhY3kiXQphY2MqMTAwCgoKCnByZWQudHJlZV9yYXcgPC0gcHJlZGljdChmaXQudHJlZSwgd3AudGVzdCkKIyBDb252ZXJ0IHRvIHByb2JhYmlsaXRpZXMKcHJlZC50cmVlX3Byb2JzIDwtIGV4cChwcmVkLnRyZWVfcmF3KSAvICgxICsgZXhwKHByZWQudHJlZV9yYXcpKQojIEV4dHJhY3QgcHJvYmFiaWxpdGllcyBmb3IgdGhlICJQb3RhYmxlIiBjbGFzcwpyb2NfY3VydmUgPC0gcm9jKGlmZWxzZSh3cC50ZXN0JFBvdGFiaWxpdHkgPT0gIlBvdGFibGUiLCAxLCAwKSwgcHJlZC50cmVlX3Byb2JzWywgIlBvdGFibGUiXSkKcGxvdChyb2NfY3VydmUsIG1haW4gPSAiUk9DIEN1cnZlIiwgY29sID0gImJsdWUiLCBsd2QgPSAyKQphYmxpbmUoYSA9IDAsIGIgPSAxLCBjb2wgPSAiZ3JheSIsIGx0eSA9IDIpCiMgUHJpbnQgQVVDCmNhdCgiQVVDOiIsIGF1Yyhyb2NfY3VydmUpLCAiXG4iKQoKCmBgYAoKU3BsaXR0aW5nIHRoZSBkYXRhIHNldCBpbnRvIHR3byBzdWJzZXRzOiBUcmFpbmluZyg4MCUpIGFuZCBUZXN0aW5nKDIwJSk6CgpgYGB7cn0Kc2V0LnNlZWQoMTk1OCkKdHJhaW4gPSBzYW1wbGUoMiwgbnJvdyh3cCksIHJlcGxhY2U9VFJVRSwgcHJvYj1jKDAuOCwgMC4yKSkKd3AudHJhaW49d3BbdHJhaW4gPT0gMSxdCndwLnRlc3Q9d3BbdHJhaW4gPT0gMixdCgoKCmZpdC50cmVlID0gcnBhcnQoUG90YWJpbGl0eSB+IC4sIGRhdGE9d3AudHJhaW4sIG1ldGhvZCA9ICJjbGFzcyIsIGNwPTAuMDA4KQpmaXQudHJlZQoKcnBhcnQucGxvdChmaXQudHJlZSkKCmZpdC50cmVlJHZhcmlhYmxlLmltcG9ydGFuY2UKCnByZWQudHJlZSA9IHByZWRpY3QoZml0LnRyZWUsIHdwLnRlc3QsIHR5cGUgPSAiY2xhc3MiKQpyZSA8LSB0YWJsZShwcmVkLnRyZWUsIHdwLnRlc3QkUG90YWJpbGl0eSkKCmNvX3JlIDwtIGNvbmZ1c2lvbk1hdHJpeChyZSkKcHJpbnQoY29fcmUpCmFzLm1hdHJpeChjb19yZSwgd2hhdCA9ICJjbGFzc2VzIikKYWNjIDwtIGNvX3JlJG92ZXJhbGxbIkFjY3VyYWN5Il0KYWNjKjEwMAoKcGxvdGNwKGZpdC50cmVlKQpwcmludGNwKGZpdC50cmVlKQoKIyBFeHBsaWNpdGx5IHJlcXVlc3QgdGhlIGxvd2VzdCBjcCB2YWx1ZQpmaXQudHJlZSRjcHRhYmxlW3doaWNoLm1pbihmaXQudHJlZSRjcHRhYmxlWywieGVycm9yIl0pLCJDUCJdCgpiZXN0Y3AgPC1maXQudHJlZSRjcHRhYmxlW3doaWNoLm1pbihmaXQudHJlZSRjcHRhYmxlWywieGVycm9yIl0pLCJDUCJdCnBydW5lZC50cmVlIDwtIHBydW5lKGZpdC50cmVlLCBjcCA9IGJlc3RjcCkKcnBhcnQucGxvdChwcnVuZWQudHJlZSkKCnByZWQucHJ1bmUgPSBwcmVkaWN0KHBydW5lZC50cmVlLCB3cC50ZXN0LCB0eXBlPSJjbGFzcyIpCgpyZSA8LSB0YWJsZShwcmVkLnBydW5lLCB3cC50ZXN0JFBvdGFiaWxpdHkpCgpjb19yZSA8LSBjb25mdXNpb25NYXRyaXgocmUpCnByaW50KGNvX3JlKQphcy5tYXRyaXgoY29fcmUsIHdoYXQgPSAiY2xhc3NlcyIpCmFjYyA8LSBjb19yZSRvdmVyYWxsWyJBY2N1cmFjeSJdCmFjYyoxMDAKCgpwcmVkLnRyZWVfcmF3IDwtIHByZWRpY3QoZml0LnRyZWUsIHdwLnRlc3QpCnByZWQudHJlZV9wcm9icyA8LSBleHAocHJlZC50cmVlX3JhdykgLyAoMSArIGV4cChwcmVkLnRyZWVfcmF3KSkKcm9jX2N1cnZlIDwtIHJvYyhpZmVsc2Uod3AudGVzdCRQb3RhYmlsaXR5ID09ICJQb3RhYmxlIiwgMSwgMCksIHByZWQudHJlZV9wcm9ic1ssICJQb3RhYmxlIl0pCnBsb3Qocm9jX2N1cnZlLCBtYWluID0gIlJPQyBDdXJ2ZSIsIGNvbCA9ICJibHVlIiwgbHdkID0gMikKYWJsaW5lKGEgPSAwLCBiID0gMSwgY29sID0gImdyYXkiLCBsdHkgPSAyKQojIFByaW50IEFVQwpjYXQoIkFVQzoiLCBhdWMocm9jX2N1cnZlKSwgIlxuIikKCgpgYGAKClNwbGl0dGluZyB0aGUgZGF0YSBzZXQgaW50byB0d28gc3Vic2V0czogVHJhaW5pbmcoOTAlKSBhbmQgVGVzdGluZygxMCUpOgoKYGBge3J9CnNldC5zZWVkKDE5NTgpCnRyYWluID0gc2FtcGxlKDIsIG5yb3cod3ApLCByZXBsYWNlPVRSVUUsIHByb2I9YygwLjksIDAuMSkpCndwLnRyYWluPXdwW3RyYWluID09IDEsXQp3cC50ZXN0PXdwW3RyYWluID09IDIsXQoKCgpmaXQudHJlZSA9IHJwYXJ0KFBvdGFiaWxpdHkgfiAuLCBkYXRhPXdwLnRyYWluLCBtZXRob2QgPSAiY2xhc3MiLCBjcD0wLjAwOCkKZml0LnRyZWUKCnJwYXJ0LnBsb3QoZml0LnRyZWUpCgpmaXQudHJlZSR2YXJpYWJsZS5pbXBvcnRhbmNlCgpwcmVkLnRyZWUgPSBwcmVkaWN0KGZpdC50cmVlLCB3cC50ZXN0LCB0eXBlID0gImNsYXNzIikKcmUgPC0gdGFibGUocHJlZC50cmVlLCB3cC50ZXN0JFBvdGFiaWxpdHkpCgpjb19yZSA8LSBjb25mdXNpb25NYXRyaXgocmUpCnByaW50KGNvX3JlKQphcy5tYXRyaXgoY29fcmUsIHdoYXQgPSAiY2xhc3NlcyIpCmFjYyA8LSBjb19yZSRvdmVyYWxsWyJBY2N1cmFjeSJdCmFjYyoxMDAKCnBsb3RjcChmaXQudHJlZSkKcHJpbnRjcChmaXQudHJlZSkKCiMgRXhwbGljaXRseSByZXF1ZXN0IHRoZSBsb3dlc3QgY3AgdmFsdWUKZml0LnRyZWUkY3B0YWJsZVt3aGljaC5taW4oZml0LnRyZWUkY3B0YWJsZVssInhlcnJvciJdKSwiQ1AiXQoKYmVzdGNwIDwtZml0LnRyZWUkY3B0YWJsZVt3aGljaC5taW4oZml0LnRyZWUkY3B0YWJsZVssInhlcnJvciJdKSwiQ1AiXQpwcnVuZWQudHJlZSA8LSBwcnVuZShmaXQudHJlZSwgY3AgPSBiZXN0Y3ApCnJwYXJ0LnBsb3QocHJ1bmVkLnRyZWUpCgpwcmVkLnBydW5lID0gcHJlZGljdChwcnVuZWQudHJlZSwgd3AudGVzdCwgdHlwZT0iY2xhc3MiKQoKcmUgPC0gdGFibGUocHJlZC5wcnVuZSwgd3AudGVzdCRQb3RhYmlsaXR5KQoKY29fcmUgPC0gY29uZnVzaW9uTWF0cml4KHJlKQpwcmludChjb19yZSkKYXMubWF0cml4KGNvX3JlLCB3aGF0ID0gImNsYXNzZXMiKQphY2MgPC0gY29fcmUkb3ZlcmFsbFsiQWNjdXJhY3kiXQphY2MqMTAwCgoKCnByZWQudHJlZV9yYXcgPC0gcHJlZGljdChmaXQudHJlZSwgd3AudGVzdCkKcHJlZC50cmVlX3Byb2JzIDwtIGV4cChwcmVkLnRyZWVfcmF3KSAvICgxICsgZXhwKHByZWQudHJlZV9yYXcpKQpyb2NfY3VydmUgPC0gcm9jKGlmZWxzZSh3cC50ZXN0JFBvdGFiaWxpdHkgPT0gIlBvdGFibGUiLCAxLCAwKSwgcHJlZC50cmVlX3Byb2JzWywgIlBvdGFibGUiXSkKcGxvdChyb2NfY3VydmUsIG1haW4gPSAiUk9DIEN1cnZlIiwgY29sID0gImJsdWUiLCBsd2QgPSAyKQphYmxpbmUoYSA9IDAsIGIgPSAxLCBjb2wgPSAiZ3JheSIsIGx0eSA9IDIpCiMgUHJpbnQgQVVDCmNhdCgiQVVDOiIsIGF1Yyhyb2NfY3VydmUpLCAiXG4iKQpgYGAKCiMjIyBDb21wYXJpc29uIENyaXRlcmlhOgoKIyMjIyBGb3IgZWFjaCBJbmZvcm1hdGlvbiBHYWluLCBHYWluIFJhdGlvKDUuMCksIGFuZCBHaW5pIGluZGV4IHNwbGl0dGluZyB0aGUgZGF0YSBzZXQgaW50byB0d28gc3Vic2V0czoKCiMjIyMjIFRyYWluaW5nKDkwJSkgYW5kIFRlc3RpbmcoMTAlKToKCnwgICAgICAgICAgICAgfCBJbmZvcm1hdGlvbiBHYWluIHwgR2FpbiBSYXRpbyB8IEdpbmkgaW5kZXggfAp8LS0tLS0tLS0tLS0tLXwtLS0tLS0tLS0tLS0tLS0tLS18LS0tLS0tLS0tLS0tfC0tLS0tLS0tLS0tLXwKfCBBY2N1cmFjeSAgICB8IDU2LjQ5JSAgICAgICAgICAgfCA2Mi4xNCUgICAgIHwgNTYuNTAlICAgICB8CnwgcHJlY2lzaW9uICAgfCA1OC43MSUgICAgICAgICAgIHwgNjIuNTklICAgICB8IDU4LjYwJSAgICAgfAp8IHNlbnNpdGl2aXR5IHwgODcuNTAlICAgICAgICAgICB8IDg4LjQ2JSAgICAgfCA1OC42MCUgICAgIHwKfCBzcGVjaWZpY2l0eSB8IDEyLjMzJSAgICAgICAgICAgfCAyNC42NiUgICAgIHwgMTAuOTYlICAgICB8CgojIyMjIyBUcmFpbmluZyg4MCUpIGFuZCBUZXN0aW5nKDIwJSk6Cgp8ICAgICAgICAgICAgIHwgSW5mb3JtYXRpb24gR2FpbiB8IEdhaW4gUmF0aW8gfCBHaW5pIGluZGV4IHwKfC0tLS0tLS0tLS0tLS18LS0tLS0tLS0tLS0tLS0tLS0tfC0tLS0tLS0tLS0tLXwtLS0tLS0tLS0tLS18CnwgQWNjdXJhY3kgICAgfCA1Ny40MiUgICAgICAgICAgIHwgNTYuODYlICAgICB8IDU3LjcwJSAgICAgfAp8IHByZWNpc2lvbiAgIHwgNTcuMTQlICAgICAgICAgICB8IDU2LjkzJSAgICAgfCA1Ny40MCUgICAgIHwKfCBzZW5zaXRpdml0eSB8IDk2JSAgICAgICAgICAgICAgfCA5NC41MCUgICAgIHwgOTUlICAgICAgICB8Cnwgc3BlY2lmaWNpdHkgfCA4LjI4JSAgICAgICAgICAgIHwgOC45MiUgICAgICB8IDEwLjE5JSAgICAgfAoKIyMjIyMgVHJhaW5pbmcoNzAlKSBhbmQgVGVzdGluZygzMCUpOgoKfCAgICAgICAgICAgICB8IEluZm9ybWF0aW9uIEdhaW4gfCBHYWluIFJhdGlvIHwgR2luaSBpbmRleCB8CnwtLS0tLS0tLS0tLS0tfC0tLS0tLS0tLS0tLS0tLS0tLXwtLS0tLS0tLS0tLS18LS0tLS0tLS0tLS0tfAp8IEFjY3VyYWN5ICAgIHwgNTguNjMlICAgICAgICAgICB8IDU5LjAxJSAgICAgfCA1OS45NiUgICAgIHwKfCBwcmVjaXNpb24gICB8IDU5LjQzJSAgICAgICAgICAgfCA1OS43OSUgICAgIHwgNjAuNjQlICAgICB8Cnwgc2Vuc2l0aXZpdHkgfCA5NC4yMSUgICAgICAgICAgIHwgOTMuMjUlICAgICB8IDkxLjY0JSAgICAgfAp8IHNwZWNpZmljaXR5IHwgNy40MSUgICAgICAgICAgICB8IDkuNzIlICAgICAgfCAxNC4zNSUgICAgIHwKCiMjIyMgRm9yIEdhaW4gUmF0aW8oNC41KSB3aXRoIEstZm9sZHM6Cgp8ICAgICAgICAgICAgIHwgSz0zICAgIHwgSz01ICAgIHwgSz0xMCAgIHwKfC0tLS0tLS0tLS0tLS18LS0tLS0tLS18LS0tLS0tLS18LS0tLS0tLS18CnwgQWNjdXJhY3kgICAgfCA2Mi4xNyUgfCA2Mi4xNyUgfCA5Mi4yMyUgfAp8IHByZWNpc2lvbiAgIHwgNTguNzElIHwgNjEuODMlIHwgOTEuNjclIHwKfCBzZW5zaXRpdml0eSB8IDk5LjA2JSB8IDk5LjA2JSB8IDk1Ljk3JSB8Cnwgc3BlY2lmaWNpdHkgfCA0LjY4JSAgfCA0LjY4JSAgfCA4Ni40MCUgfAoKQXMgc2hvd24gaW4gdGhlIGNvbXBhcmlzb24gdGhlIGJlc3QgdGVjaG5pcXVlIHRvIGNob29zZSBpcyBHYWluIFJhaW8gRHVlIHRvIHRoZSBoaWdoIGFjY3VyYWN5CgpgYGB7cn0Kc3VtbWFyeSh3YXRlcl9wb3RhYmlsaXR5KQpzdHIod2F0ZXJfcG90YWJpbGl0eSkKYGBgCgojIyBDbHVzdGVyaW5nCgojIGRldGVybWluZSBhbmQgdmlzdWFsaXplIG9wdGltYWwgbnVtYmVyIG9mIGNsdXN0ZXJzOgoKV2Ugd2lsbCBleHBlcmltZW50IHdpdGggZm91ciByYW5kb20gc2l6ZXMgb2YgayBmb3IgY2x1c3RlcmluZyBpbiBvcmRlciB0byBmaW5kIHRoZSBpZGVhbCBudW1iZXIgb2YgY2x1c3RlcnMgKGspIGZvciBvdXIgZGF0YXNldC4gV2Ugd2lsbCB1c2UgYSBudW1iZXIgb2YgdGVjaG5pcXVlcyAoY2FsY3VsYXRlIGF2ZXJhZ2Ugc2lsaG91ZXR0ZSwgdG90YWwgd2l0aGluLWNsdXN0ZXIgc3VtIG9mIHNxdWFyZSwga21lYW5zcnVucywgYW5kIEJDdWJlZCAocHJlY2lzaW9uIGFuZCByZWNhbGwpKSB0byBoZWxwIHdpdGggdGhpcyBkZXRlcm1pbmF0aW9uIGluIG9yZGVyIHRvIGhlbHAgZmluZCB0aGUgYmVzdCBrIHZhbHVlIGZvciBvdXIgcGFydGljdWxhciBkYXRhc2V0LgoKIyMjIFNjYWxlIGRhdGEgZmlyc3Q6CgpDb25maXJtIHRoYXQgYWxsIHRoZSBjb2x1bW5zIHlvdSBhcmUgdHJ5aW5nIHRvIHNjYWxlIGFyZSBpbmRlZWQgbnVtZXJpYy4gWW91IGNhbiB1c2Ugc2FwcGx5KCkgdG8gY2hlY2sgYW5kIGNvZXJjZSB0aGVtIHRvIG51bWVyaWMgaWYgbmVjZXNzYXJ5LgoKc2luZWMgYWxsIGNvdWxtZSBhcmUgbnVtZXJpYyB3ZSB3bGwgc2NhbGUgYWxsIG9mIHRoZW0gZXhwZXQgY2xhc3MgbGFiZWwgYW5kIHdlIHNhdmVkIGl0IGluIGRhdGFzZXQgY2FsbGVkIENsdXN0ZXIgYW5kIHdlIHVzZWQgaXQgaW4gQ2x1c3RyaW5nCgpgYGB7cn0Kd2F0ZXJfcG90YWJpbGl0eTwtIHNhcHBseSh3YXRlcl9wb3RhYmlsaXR5LCBhcy5udW1lcmljKQoKZGF0YV9mb3JfY2x1c3RlciA8LSBzY2FsZSh3YXRlcl9wb3RhYmlsaXR5WywgIWNvbG5hbWVzKHdhdGVyX3BvdGFiaWxpdHkpICVpbiUgIlBvdGFiaWxpdHkiXSkKI3dlIHVzZSAhY29sbmFtZXMod2F0ZXJfcG90YWJpbGl0eSkgJWluJSAiUG90YWJpbGl0eSIgdG8gZXhjbHVkZSB0aGUgIlBvdGFiaWxpdHkiIGNvbHVtbgpWaWV3KGRhdGFfZm9yX2NsdXN0ZXIpCmBgYAoKIyMgQ2x1c3RyaW5nMQoKIyMjIEstbWVhbnMKCmBgYHtyfQojIDMtIHJ1biBrLW1lYW5zIGNsdXN0ZXJpbmcgdG8gZmluZCAyIGNsdXN0ZXJzCiNzZXQgYSBzZWVkIGZvciByYW5kb20gbnVtYmVyIGdlbmVyYXRpb24gIHRvIG1ha2UgdGhlIHJlc3VsdHMgcmVwcm9kdWNpYmxlCnNldC5zZWVkKDg5NTMpCmttZWFucy5yZXN1bHQgPC0ga21lYW5zKGRhdGFfZm9yX2NsdXN0ZXIsMikKIyBwcmludCB0aGUgY2x1c3Rlcm5nIHJlc3VsdAprbWVhbnMucmVzdWx0CmBgYAoKIyMjIHZpc3VhbGl6ZSBjbHVzdGVyaW5nCgpgYGB7cn0KIyB2aXN1YWxpemUgY2x1c3RlcmluZyAoMiBjbHVzdGVycykKZnZpel9jbHVzdGVyKGttZWFucy5yZXN1bHQsIGRhdGEgPSBkYXRhX2Zvcl9jbHVzdGVyKQpgYGAKCiMjIyBoaWVyY3JjaGljYWwgY2x1c3RlcmluZwoKd2UgdG9vayA1MCBzYW1wbGUgdG8gbWFrZSBpdCBtb3JlIHVuZGVyc3RhYmFsZQoKYGBge3J9CiMgZHJhdyBhIHNhbXBsZSBvZiA1MCByZWNvcmRzIGZyb20gdGhlIGRhdGEsIHNvIHRoYXQgdGhlIGNsdXN0ZXJpbmcgcGxvdCB3aWxsIG5vdCBiZSBvdmVyIGNyb3dkZWQgYW5kIGVhc3kgdG8gdW5kcmVzdGFuZCAKaWR4PC1zYW1wbGUoMTpkaW0oZGF0YV9mb3JfY2x1c3RlcilbMV0sIDUwKQpzYW1wbGVfYzE8LWRhdGFfZm9yX2NsdXN0ZXJbaWR4LCBdCgojIyBoaWVyY3JjaGljYWwgY2x1c3RlcmluZwpoYy5jdXQ8LSBoY3V0KHNhbXBsZV9jMSwgayA9IDIsIGhjX21ldGhvZD0gImNvbXBsZXRlIikKYGBgCgojIyMgVmlzdWFsaXplIGRlbmRyb2dyYW0gYW5kIHNhbXBsZSBDbHVzdGVyaW5nCgpkZW5kcm9ncmFtIGlzIGEgdHJlZSBkaWFncmFtIHRoYXQgZGlzcGxheXMgdGhlIGFycmFuZ2VtZW50IG9mIGRhdGEgcG9pbnRzIGluIGEgaGllcmFyY2hpY2FsIG9yZGVyIGJhc2VkIG9uIHRoZWlyIHNpbWlsYXJpdHkgb3IgZGlzc2ltaWxhcml0eS4KCmBgYHtyfQojIFZpc3VhbGl6ZSBkZW5kcm9ncmFtCmZ2aXpfZGVuZChoYy5jdXQscmVjdD0gVFJVRSkKIyBWaXN1YWxpemUgY2x1c3Rlcgpmdml6X2NsdXN0ZXIoaGMuY3V0LCBlbGxpcHNlLnR5cGU9ICJjb252ZXgiKQpgYGAKCiMjIyBhdmVyYWdlIHNpbGhvdWV0dGUKClRoaXMgbWV0aG9kIGNhbGN1bGF0ZXMgdGhlIGF2ZXJhZ2Ugc2lsaG91ZXR0ZSB3aWR0aCBmb3IgZGlmZmVyZW50IHZhbHVlcyBvZiBrLCBkZXRlcm1pbmluZyBob3cgd2VsbCBkYXRhIHBvaW50cyBmaXQgaW50byB0aGVpciBhc3NpZ25lZCBjbHVzdGVycy4KCmBgYHtyfQogI2F2ZXJhZ2Ugc2lsaG91ZXR0ZSBmb3IgZWFjaCBjbHVzdGVycyAKCmF2Z19zaWwgPC0gc2lsaG91ZXR0ZShrbWVhbnMucmVzdWx0JGNsdXN0ZXIsZGlzdChkYXRhX2Zvcl9jbHVzdGVyKSkgI2EgZGlzc2ltaWxhcml0eSBvYmplY3QgaW5oZXJpdGluZyBmcm9tIGNsYXNzIGRpc3Qgb3IgY29lcmNpYmxlIHRvIG9uZS4gSWYgbm90IHNwZWNpZmllZCwgZG1hdHJpeCBtdXN0IGJlLgpmdml6X3NpbGhvdWV0dGUoYXZnX3NpbCkjay1tZWFucyBjbHVzdGVyaW5nIHdpdGggZXN0aW1hdGluZyBrIGFuZCBpbml0aWFsaXphdGlvbnMKYGBgCgojIyMgQkN1YmVkIHByZWNpc2lvbiBhbmQgcmVjYWxsCgpCQ3ViZWQgcHJlY2lzaW9uIGFuZCByZWNhbGwgYXJlIG1ldHJpY3MgdXNlZCB0byBldmFsdWF0ZSB0aGUgcGVyZm9ybWFuY2Ugb2YgY2x1c3RlcmluZyBhbGdvcml0aG1zLCBwYXJ0aWN1bGFybHkgaW4gdGhlIGNvbnRleHQgb2YgZXZhbHVhdGluZyB0aGUgcXVhbGl0eSBvZiBjbHVzdGVyaW5nIGFzc2lnbm1lbnRzIGZvciBpbmRpdmlkdWFsIGRhdGEgcG9pbnRzLgoKYGBge3J9CgpjbHVzdGVyX2Fzc2lnbm1lbnRzIDwtIGMoa21lYW5zLnJlc3VsdCRjbHVzdGVyKQpncm91bmRfdHJ1dGhfbGFiZWxzIDwtIGMod2F0ZXJfcG90YWJpbGl0eSkKZGF0YSA8LSBkYXRhLmZyYW1lKGNsdXN0ZXIgPSBjbHVzdGVyX2Fzc2lnbm1lbnRzLCBsYWJlbCA9IGdyb3VuZF90cnV0aF9sYWJlbHMpCgojIEZ1bmN0aW9uIHRvIGNhbGN1bGF0ZSBCQ3ViZWQgcHJlY2lzaW9uIGFuZCByZWNhbGwKY2FsY3VsYXRlX2JjdWJlZF9tZXRyaWNzIDwtIGZ1bmN0aW9uKGRhdGEpIHsKICBuIDwtIG5yb3coZGF0YSkKICBwcmVjaXNpb25fc3VtIDwtIDAKICByZWNhbGxfc3VtIDwtIDAKCiAgZm9yIChpIGluIDE6bikgewogICAgY2x1c3RlciA8LSBkYXRhJGNsdXN0ZXJbaV0KICAgIGxhYmVsIDwtIGRhdGEkbGFiZWxbaV0KICAgIAojIENvdW50IHRoZSBudW1iZXIgb2YgaXRlbXMgZnJvbSB0aGUgc2FtZSBjYXRlZ29yeSB3aXRoaW4gdGhlIHNhbWUgY2x1c3RlcgpzYW1lX2NhdGVnb3J5X3NhbWVfY2x1c3RlciA8LSBzdW0oZGF0YSRsYWJlbFtkYXRhJGNsdXN0ZXIgPT0gY2x1c3Rlcl0gPT0gbGFiZWwpCiAgICAKIyBDb3VudCB0aGUgdG90YWwgbnVtYmVyIG9mIGl0ZW1zIGluIHRoZSBzYW1lIGNsdXN0ZXIKdG90YWxfc2FtZV9jbHVzdGVyIDwtIHN1bShkYXRhJGNsdXN0ZXIgPT0gY2x1c3RlcikKICAgIAojIENvdW50IHRoZSB0b3RhbCBudW1iZXIgb2YgaXRlbXMgd2l0aCB0aGUgc2FtZSBjYXRlZ29yeQp0b3RhbF9zYW1lX2NhdGVnb3J5IDwtIHN1bShkYXRhJGxhYmVsID09IGxhYmVsKQogICAgCiMgQ2FsY3VsYXRlIHByZWNpc2lvbiBhbmQgcmVjYWxsIGZvciB0aGUgY3VycmVudCBpdGVtIGFuZCBhZGQgdGhlbSB0byB0aGUgc3VtcwpwcmVjaXNpb25fc3VtIDwtIHByZWNpc2lvbl9zdW0gKyBzYW1lX2NhdGVnb3J5X3NhbWVfY2x1c3RlciAvdG90YWxfc2FtZV9jbHVzdGVyCnJlY2FsbF9zdW0gPC0gcmVjYWxsX3N1bSArIHNhbWVfY2F0ZWdvcnlfc2FtZV9jbHVzdGVyIC8gdG90YWxfc2FtZV9jYXRlZ29yeQogIH0KCiAgIyBDYWxjdWxhdGUgYXZlcmFnZSBwcmVjaXNpb24gYW5kIHJlY2FsbAogIHByZWNpc2lvbiA8LSBwcmVjaXNpb25fc3VtIC8gbgogIHJlY2FsbCA8LSByZWNhbGxfc3VtIC8gbgoKICByZXR1cm4obGlzdChwcmVjaXNpb24gPSBwcmVjaXNpb24sIHJlY2FsbCA9IHJlY2FsbCkpCn0KCiMgQ2FsY3VsYXRlIEJDdWJlZCBwcmVjaXNpb24gYW5kIHJlY2FsbAptZXRyaWNzIDwtIGNhbGN1bGF0ZV9iY3ViZWRfbWV0cmljcyhkYXRhKQoKCiMgRXh0cmFjdCBwcmVjaXNpb24gYW5kIHJlY2FsbCBmcm9tIHRoZSBtZXRyaWNzCnByZWNpc2lvbiA8LSBtZXRyaWNzJHByZWNpc2lvbgpyZWNhbGwgPC0gbWV0cmljcyRyZWNhbGwKCiMgUHJpbnQgdGhlIHJlc3VsdHMKY2F0KCJCQ3ViZWQgUHJlY2lzaW9uOiIsIHByZWNpc2lvbiwgIlxuIikKY2F0KCJCQ3ViZWQgUmVjYWxsOiIsIHJlY2FsbCwgIlxuIikKCmBgYAoKIyMgQ2x1c3RyaW5nMgoKIyMjIEstbWVhbnMKCnJ1biBrLW1lYW5zIGNsdXN0ZXJpbmcgdG8gZmluZCAzIGNsdXN0ZXJzIHNldCBhIHNlZWQgZm9yIHJhbmRvbSBudW1iZXIgZ2VuZXJhdGlvbiB0byBtYWtlIHRoZSByZXN1bHRzIHJlcHJvZHVjaWJsZQoKYGBge3J9CnNldC5zZWVkKDg5NTMpCmttZWFucy5yZXN1bHQgPC0ga21lYW5zKGRhdGFfZm9yX2NsdXN0ZXIsMykKIyBwcmludCB0aGUgQ2x1c3RyaW5nIHJlc3VsdAprbWVhbnMucmVzdWx0CmBgYAoKIyMjIHZpc3VhbGl6ZSBjbHVzdGVyaW5nCgpgYGB7cn0KIyB2aXN1YWxpemUgY2x1c3RlcmluZyAoMyBjbHVzdGVycykKCmZ2aXpfY2x1c3RlcihrbWVhbnMucmVzdWx0LCBkYXRhID0gZGF0YV9mb3JfY2x1c3RlcikKYGBgCgojIyMgaGllcmNyY2hpY2FsIGNsdXN0ZXJpbmcKCmBgYHtyfQojIGRyYXcgYSBzYW1wbGUgb2YgNTAgcmVjb3JkcyBmcm9tIHRoZSBkYXRhLCBzbyB0aGF0IHRoZSBjbHVzdGVyaW5nIHBsb3Qgd2lsbCBub3QgYmUgb3ZlciBjcm93ZGVkIGFuZCBlYXN5IHRvIHVuZHJlc3RhbmQgCgppZHgyPC1zYW1wbGUoMTpkaW0oZGF0YV9mb3JfY2x1c3RlcilbMV0sIDUwKQpzYW1wbGVfYzI8LWRhdGFfZm9yX2NsdXN0ZXJbaWR4MiwgXQoKIyMgaGllcmNyY2hpY2FsIGNsdXN0ZXJpbmcKaGMyLmN1dDwtIGhjdXQoc2FtcGxlX2MyLCBrID0gMywgaGNfbWV0aG9kPSAiY29tcGxldGUiKQpgYGAKCiMjIyBWaXN1YWxpemUgZGVuZHJvZ3JhbQoKZGVuZHJvZ3JhbSBpcyBhIHRyZWUgZGlhZ3JhbSB0aGF0IGRpc3BsYXlzIHRoZSBhcnJhbmdlbWVudCBvZiBkYXRhIHBvaW50cyBpbiBhIGhpZXJhcmNoaWNhbCBvcmRlciBiYXNlZCBvbiB0aGVpciBzaW1pbGFyaXR5IG9yIGRpc3NpbWlsYXJpdHkuCgpgYGB7cn0KZnZpel9kZW5kKGhjMi5jdXQscmVjdD0gVFJVRSkKIyBWaXN1YWxpemUgY2x1c3Rlcgpmdml6X2NsdXN0ZXIoaGMyLmN1dCwgZWxsaXBzZS50eXBlPSAiY29udmV4IikKYGBgCgojIyMgYXZlcmFnZSBzaWxob3VldHRlCgpUaGlzIG1ldGhvZCBjYWxjdWxhdGVzIHRoZSBhdmVyYWdlIHNpbGhvdWV0dGUgd2lkdGggZm9yIGRpZmZlcmVudCB2YWx1ZXMgb2YgaywgZGV0ZXJtaW5pbmcgaG93IHdlbGwgZGF0YSBwb2ludHMgZml0IGludG8gdGhlaXIgYXNzaWduZWQgY2x1c3RlcnMuCgpgYGB7cn0KICNhdmVyYWdlIHNpbGhvdWV0dGUgZm9yIGVhY2ggY2x1c3RlcnMgCgphdmdfc2lsIDwtIHNpbGhvdWV0dGUoa21lYW5zLnJlc3VsdCRjbHVzdGVyLGRpc3QoZGF0YV9mb3JfY2x1c3RlcikpICNhIGRpc3NpbWlsYXJpdHkgb2JqZWN0IGluaGVyaXRpbmcgZnJvbSBjbGFzcyBkaXN0IG9yIGNvZXJjaWJsZSB0byBvbmUuIElmIG5vdCBzcGVjaWZpZWQsIGRtYXRyaXggbXVzdCBiZS4KZnZpel9zaWxob3VldHRlKGF2Z19zaWwpI2stbWVhbnMgY2x1c3RlcmluZyB3aXRoIGVzdGltYXRpbmcgayBhbmQgaW5pdGlhbGl6YXRpb25zCmBgYAoKIyMjIEJDdWJlZCBwcmVjaXNpb24gYW5kIHJlY2FsbAoKQkN1YmVkIHByZWNpc2lvbiBhbmQgcmVjYWxsIGFyZSBtZXRyaWNzIHVzZWQgdG8gZXZhbHVhdGUgdGhlIHBlcmZvcm1hbmNlIG9mIGNsdXN0ZXJpbmcgYWxnb3JpdGhtcywgcGFydGljdWxhcmx5IGluIHRoZSBjb250ZXh0IG9mIGV2YWx1YXRpbmcgdGhlIHF1YWxpdHkgb2YgY2x1c3RlcmluZyBhc3NpZ25tZW50cyBmb3IgaW5kaXZpZHVhbCBkYXRhIHBvaW50cy4KCmBgYHtyfQoKY2x1c3Rlcl9hc3NpZ25tZW50cyA8LSBjKGttZWFucy5yZXN1bHQkY2x1c3RlcikKZ3JvdW5kX3RydXRoX2xhYmVscyA8LSBjKHdhdGVyX3BvdGFiaWxpdHkpCmRhdGEgPC0gZGF0YS5mcmFtZShjbHVzdGVyID0gY2x1c3Rlcl9hc3NpZ25tZW50cywgbGFiZWwgPSBncm91bmRfdHJ1dGhfbGFiZWxzKQoKIyBGdW5jdGlvbiB0byBjYWxjdWxhdGUgQkN1YmVkIHByZWNpc2lvbiBhbmQgcmVjYWxsCmNhbGN1bGF0ZV9iY3ViZWRfbWV0cmljcyA8LSBmdW5jdGlvbihkYXRhKSB7CiAgbiA8LSBucm93KGRhdGEpCiAgcHJlY2lzaW9uX3N1bSA8LSAwCiAgcmVjYWxsX3N1bSA8LSAwCgogIGZvciAoaSBpbiAxOm4pIHsKICAgIGNsdXN0ZXIgPC0gZGF0YSRjbHVzdGVyW2ldCiAgICBsYWJlbCA8LSBkYXRhJGxhYmVsW2ldCiAgICAKIyBDb3VudCB0aGUgbnVtYmVyIG9mIGl0ZW1zIGZyb20gdGhlIHNhbWUgY2F0ZWdvcnkgd2l0aGluIHRoZSBzYW1lIGNsdXN0ZXIKc2FtZV9jYXRlZ29yeV9zYW1lX2NsdXN0ZXIgPC0gc3VtKGRhdGEkbGFiZWxbZGF0YSRjbHVzdGVyID09IGNsdXN0ZXJdID09IGxhYmVsKQogICAgCiMgQ291bnQgdGhlIHRvdGFsIG51bWJlciBvZiBpdGVtcyBpbiB0aGUgc2FtZSBjbHVzdGVyCnRvdGFsX3NhbWVfY2x1c3RlciA8LSBzdW0oZGF0YSRjbHVzdGVyID09IGNsdXN0ZXIpCiAgICAKIyBDb3VudCB0aGUgdG90YWwgbnVtYmVyIG9mIGl0ZW1zIHdpdGggdGhlIHNhbWUgY2F0ZWdvcnkKdG90YWxfc2FtZV9jYXRlZ29yeSA8LSBzdW0oZGF0YSRsYWJlbCA9PSBsYWJlbCkKICAgIAojIENhbGN1bGF0ZSBwcmVjaXNpb24gYW5kIHJlY2FsbCBmb3IgdGhlIGN1cnJlbnQgaXRlbSBhbmQgYWRkIHRoZW0gdG8gdGhlIHN1bXMKcHJlY2lzaW9uX3N1bSA8LSBwcmVjaXNpb25fc3VtICsgc2FtZV9jYXRlZ29yeV9zYW1lX2NsdXN0ZXIgL3RvdGFsX3NhbWVfY2x1c3RlcgpyZWNhbGxfc3VtIDwtIHJlY2FsbF9zdW0gKyBzYW1lX2NhdGVnb3J5X3NhbWVfY2x1c3RlciAvIHRvdGFsX3NhbWVfY2F0ZWdvcnkKICB9CgogICMgQ2FsY3VsYXRlIGF2ZXJhZ2UgcHJlY2lzaW9uIGFuZCByZWNhbGwKICBwcmVjaXNpb24gPC0gcHJlY2lzaW9uX3N1bSAvIG4KICByZWNhbGwgPC0gcmVjYWxsX3N1bSAvIG4KCiAgcmV0dXJuKGxpc3QocHJlY2lzaW9uID0gcHJlY2lzaW9uLCByZWNhbGwgPSByZWNhbGwpKQp9CgojIENhbGN1bGF0ZSBCQ3ViZWQgcHJlY2lzaW9uIGFuZCByZWNhbGwKbWV0cmljcyA8LSBjYWxjdWxhdGVfYmN1YmVkX21ldHJpY3MoZGF0YSkKCiMgRXh0cmFjdCBwcmVjaXNpb24gYW5kIHJlY2FsbCBmcm9tIHRoZSBtZXRyaWNzCnByZWNpc2lvbiA8LSBtZXRyaWNzJHByZWNpc2lvbgpyZWNhbGwgPC0gbWV0cmljcyRyZWNhbGwKCiMgUHJpbnQgdGhlIHJlc3VsdHMKY2F0KCJCQ3ViZWQgUHJlY2lzaW9uOiIsIHByZWNpc2lvbiwgIlxuIikKY2F0KCJCQ3ViZWQgUmVjYWxsOiIsIHJlY2FsbCwgIlxuIikKCmBgYAoKIyMgQ2x1c3RyaW5nMwoKIyMjIEstbWVhbnMKCmBgYHtyfQojIDMtIHJ1biBrLW1lYW5zIGNsdXN0ZXJpbmcgdG8gZmluZCA0IGNsdXN0ZXJzCiNzZXQgYSBzZWVkIGZvciByYW5kb20gbnVtYmVyIGdlbmVyYXRpb24gIHRvIG1ha2UgdGhlIHJlc3VsdHMgcmVwcm9kdWNpYmxlCnNldC5zZWVkKDg5NTMpCmttZWFucy5yZXN1bHQgPC0ga21lYW5zKGRhdGFfZm9yX2NsdXN0ZXIsNCkKIyBwcmludCB0aGUgY2x1c3RlcmluZyByZXN1bHQKa21lYW5zLnJlc3VsdApgYGAKCiMjIyB2aXN1YWxpemUgY2x1c3RlcmluZwoKYGBge3J9CiMgdmlzdWFsaXplIGNsdXN0ZXJpbmcgKDQgY2x1c3RlcnMpCgpmdml6X2NsdXN0ZXIoa21lYW5zLnJlc3VsdCwgZGF0YSA9IGRhdGFfZm9yX2NsdXN0ZXIpCmBgYAoKIyMjIGhpZXJjcmNoaWNhbCBjbHVzdGVyaW5nCgpgYGB7cn0KIyBkcmF3IGEgc2FtcGxlIG9mIDUwIHJlY29yZHMgZnJvbSB0aGUgZGF0YSwgc28gdGhhdCB0aGUgY2x1c3RlcmluZyBwbG90IHdpbGwgbm90IGJlIG92ZXIgY3Jvd2RlZCBhbmQgZWFzeSB0byB1bmRyZXN0YW5kIAppZHgzPC1zYW1wbGUoMTpkaW0oZGF0YV9mb3JfY2x1c3RlcilbMV0sIDUwKQpzYW1wbGVfYzM8LWRhdGFfZm9yX2NsdXN0ZXJbaWR4MywgXQoKIyMgaGllcmNyY2hpY2FsY2x1c3RlcmluZwpoYzMuY3V0PC0gaGN1dChzYW1wbGVfYzMsIGsgPSA0LCBoY19tZXRob2Q9ICJjb21wbGV0ZSIpCmBgYAoKIyMjIGRlbmRyb2dyYW0KCmRlbmRyb2dyYW0gaXMgYSB0cmVlIGRpYWdyYW0gdGhhdCBkaXNwbGF5cyB0aGUgYXJyYW5nZW1lbnQgb2YgZGF0YSBwb2ludHMgaW4gYSBoaWVyYXJjaGljYWwgb3JkZXIgYmFzZWQgb24gdGhlaXIgc2ltaWxhcml0eSBvciBkaXNzaW1pbGFyaXR5LgoKYGBge3J9CiMgVmlzdWFsaXplIGRlbmRyb2dyYW0KZnZpel9kZW5kKGhjMy5jdXQscmVjdD0gVFJVRSkKIyBWaXN1YWxpemUgY2x1c3Rlcgpmdml6X2NsdXN0ZXIoaGMzLmN1dCwgZWxsaXBzZS50eXBlPSAiY29udmV4IikKYGBgCgojIyMgYXZlcmFnZSBzaWxob3VldHRlCgpUaGlzIG1ldGhvZCBjYWxjdWxhdGVzIHRoZSBhdmVyYWdlIHNpbGhvdWV0dGUgd2lkdGggZm9yIGRpZmZlcmVudCB2YWx1ZXMgb2YgaywgZGV0ZXJtaW5pbmcgaG93IHdlbGwgZGF0YSBwb2ludHMgZml0IGludG8gdGhlaXIgYXNzaWduZWQgY2x1c3RlcnMuCgpgYGB7cn0KICNhdmVyYWdlIHNpbGhvdWV0dGUgZm9yIGVhY2ggY2x1c3RlcnMgCgphdmdfc2lsIDwtIHNpbGhvdWV0dGUoa21lYW5zLnJlc3VsdCRjbHVzdGVyLGRpc3QoZGF0YV9mb3JfY2x1c3RlcikpICNhIGRpc3NpbWlsYXJpdHkgb2JqZWN0IGluaGVyaXRpbmcgZnJvbSBjbGFzcyBkaXN0IG9yIGNvZXJjaWJsZSB0byBvbmUuIElmIG5vdCBzcGVjaWZpZWQsIGRtYXRyaXggbXVzdCBiZS4KZnZpel9zaWxob3VldHRlKGF2Z19zaWwpI2stbWVhbnMgY2x1c3RlcmluZyB3aXRoIGVzdGltYXRpbmcgayBhbmQgaW5pdGlhbGl6YXRpb25zCmBgYAoKIyMjIEJDdWJlZCBwcmVjaXNpb24gYW5kIHJlY2FsbAoKQkN1YmVkIHByZWNpc2lvbiBhbmQgcmVjYWxsIGFyZSBtZXRyaWNzIHVzZWQgdG8gZXZhbHVhdGUgdGhlIHBlcmZvcm1hbmNlIG9mIGNsdXN0ZXJpbmcgYWxnb3JpdGhtcywgcGFydGljdWxhcmx5IGluIHRoZSBjb250ZXh0IG9mIGV2YWx1YXRpbmcgdGhlIHF1YWxpdHkgb2YgY2x1c3RlcmluZyBhc3NpZ25tZW50cyBmb3IgaW5kaXZpZHVhbCBkYXRhIHBvaW50cy4KCmBgYHtyfQoKY2x1c3Rlcl9hc3NpZ25tZW50cyA8LSBjKGttZWFucy5yZXN1bHQkY2x1c3RlcikKZ3JvdW5kX3RydXRoX2xhYmVscyA8LSBjKHdhdGVyX3BvdGFiaWxpdHkpCmRhdGEgPC0gZGF0YS5mcmFtZShjbHVzdGVyID0gY2x1c3Rlcl9hc3NpZ25tZW50cywgbGFiZWwgPSBncm91bmRfdHJ1dGhfbGFiZWxzKQoKIyBGdW5jdGlvbiB0byBjYWxjdWxhdGUgQkN1YmVkIHByZWNpc2lvbiBhbmQgcmVjYWxsCmNhbGN1bGF0ZV9iY3ViZWRfbWV0cmljcyA8LSBmdW5jdGlvbihkYXRhKSB7CiAgbiA8LSBucm93KGRhdGEpCiAgcHJlY2lzaW9uX3N1bSA8LSAwCiAgcmVjYWxsX3N1bSA8LSAwCgogIGZvciAoaSBpbiAxOm4pIHsKICAgIGNsdXN0ZXIgPC0gZGF0YSRjbHVzdGVyW2ldCiAgICBsYWJlbCA8LSBkYXRhJGxhYmVsW2ldCiAgICAKIyBDb3VudCB0aGUgbnVtYmVyIG9mIGl0ZW1zIGZyb20gdGhlIHNhbWUgY2F0ZWdvcnkgd2l0aGluIHRoZSBzYW1lIGNsdXN0ZXIKc2FtZV9jYXRlZ29yeV9zYW1lX2NsdXN0ZXIgPC0gc3VtKGRhdGEkbGFiZWxbZGF0YSRjbHVzdGVyID09IGNsdXN0ZXJdID09IGxhYmVsKQogICAgCiMgQ291bnQgdGhlIHRvdGFsIG51bWJlciBvZiBpdGVtcyBpbiB0aGUgc2FtZSBjbHVzdGVyCnRvdGFsX3NhbWVfY2x1c3RlciA8LSBzdW0oZGF0YSRjbHVzdGVyID09IGNsdXN0ZXIpCiAgICAKIyBDb3VudCB0aGUgdG90YWwgbnVtYmVyIG9mIGl0ZW1zIHdpdGggdGhlIHNhbWUgY2F0ZWdvcnkKdG90YWxfc2FtZV9jYXRlZ29yeSA8LSBzdW0oZGF0YSRsYWJlbCA9PSBsYWJlbCkKICAgIAojIENhbGN1bGF0ZSBwcmVjaXNpb24gYW5kIHJlY2FsbCBmb3IgdGhlIGN1cnJlbnQgaXRlbSBhbmQgYWRkIHRoZW0gdG8gdGhlIHN1bXMKcHJlY2lzaW9uX3N1bSA8LSBwcmVjaXNpb25fc3VtICsgc2FtZV9jYXRlZ29yeV9zYW1lX2NsdXN0ZXIgL3RvdGFsX3NhbWVfY2x1c3RlcgpyZWNhbGxfc3VtIDwtIHJlY2FsbF9zdW0gKyBzYW1lX2NhdGVnb3J5X3NhbWVfY2x1c3RlciAvIHRvdGFsX3NhbWVfY2F0ZWdvcnkKICB9CgogICMgQ2FsY3VsYXRlIGF2ZXJhZ2UgcHJlY2lzaW9uIGFuZCByZWNhbGwKICBwcmVjaXNpb24gPC0gcHJlY2lzaW9uX3N1bSAvIG4KICByZWNhbGwgPC0gcmVjYWxsX3N1bSAvIG4KCiAgcmV0dXJuKGxpc3QocHJlY2lzaW9uID0gcHJlY2lzaW9uLCByZWNhbGwgPSByZWNhbGwpKQp9CgojIENhbGN1bGF0ZSBCQ3ViZWQgcHJlY2lzaW9uIGFuZCByZWNhbGwKbWV0cmljcyA8LSBjYWxjdWxhdGVfYmN1YmVkX21ldHJpY3MoZGF0YSkKCiMgRXh0cmFjdCBwcmVjaXNpb24gYW5kIHJlY2FsbCBmcm9tIHRoZSBtZXRyaWNzCnByZWNpc2lvbiA8LSBtZXRyaWNzJHByZWNpc2lvbgpyZWNhbGwgPC0gbWV0cmljcyRyZWNhbGwKCiMgUHJpbnQgdGhlIHJlc3VsdHMKY2F0KCJCQ3ViZWQgUHJlY2lzaW9uOiIsIHByZWNpc2lvbiwgIlxuIikKY2F0KCJCQ3ViZWQgUmVjYWxsOiIsIHJlY2FsbCwgIlxuIikKCmBgYAoKIyMgQ2x1c3RyaW5nNAoKIyMjIyBLLW1lYW5zIHJ1biBrLW1lYW5zIGNsdXN0ZXJpbmcgdG8gZmluZCA1IGNsdXN0ZXJzCgpgYGB7cn0KI3NldCBhIHNlZWQgZm9yIHJhbmRvbSBudW1iZXIgZ2VuZXJhdGlvbiAgdG8gbWFrZSB0aGUgcmVzdWx0cyByZXByb2R1Y2libGUKc2V0LnNlZWQoODk1MykKa21lYW5zLnJlc3VsdCA8LSBrbWVhbnMoZGF0YV9mb3JfY2x1c3Rlciw1KQojIHByaW50IHRoZSBjbHVzdGVybmcgcmVzdWx0CmttZWFucy5yZXN1bHQKYGBgCgojIyMgdmlzdWFsaXplIGNsdXN0ZXJpbmcKCmBgYHtyfQojIHZpc3VhbGl6ZSBjbHVzdGVyaW5nICg1IGNsdXN0ZXJzKQoKZnZpel9jbHVzdGVyKGttZWFucy5yZXN1bHQsIGRhdGEgPSBkYXRhX2Zvcl9jbHVzdGVyKQpgYGAKCiMjIyBoaWVyY3JjaGljYWwgY2x1c3RlcmluZwoKYGBge3J9CiMgZHJhdyBhIHNhbXBsZSBvZiA1MCByZWNvcmRzIGZyb20gdGhlIGRhdGEsIHNvIHRoYXQgdGhlIGNsdXN0ZXJpbmcgcGxvdCB3aWxsIG5vdCBiZSBvdmVyIGNyb3dkZWQgYW5kIGVhc3kgdG8gdW5kcmVzdGFuZCAKaWR4NDwtc2FtcGxlKDE6ZGltKGRhdGFfZm9yX2NsdXN0ZXIpWzFdLCA1MCkKc2FtcGxlX2M0PC1kYXRhX2Zvcl9jbHVzdGVyW2lkeDQsIF0KCiMjIGhpZXJjcmNoaWNhbGNsdXN0ZXJpbmcKaGM0LmN1dDwtIGhjdXQoc2FtcGxlX2M0LCBrID0gNSwgaGNfbWV0aG9kPSAiY29tcGxldGUiKQpgYGAKCiMjIyBkZW5kcm9ncmFtCgpkZW5kcm9ncmFtIGlzIGEgdHJlZSBkaWFncmFtIHRoYXQgZGlzcGxheXMgdGhlIGFycmFuZ2VtZW50IG9mIGRhdGEgcG9pbnRzIGluIGEgaGllcmFyY2hpY2FsIG9yZGVyIGJhc2VkIG9uIHRoZWlyIHNpbWlsYXJpdHkgb3IgZGlzc2ltaWxhcml0eS4KCmBgYHtyfQojIFZpc3VhbGl6ZSBkZW5kcm9ncmFtCmZ2aXpfZGVuZChoYzQuY3V0LHJlY3Q9IFRSVUUpCiMgVmlzdWFsaXplIGNsdXN0ZXIKZnZpel9jbHVzdGVyKGhjNC5jdXQsIGVsbGlwc2UudHlwZT0gImNvbnZleCIpCmBgYAoKIyMjIGF2ZXJhZ2Ugc2lsaG91ZXR0ZQoKVGhpcyBtZXRob2QgY2FsY3VsYXRlcyB0aGUgYXZlcmFnZSBzaWxob3VldHRlIHdpZHRoIGZvciBkaWZmZXJlbnQgdmFsdWVzIG9mIGssIGRldGVybWluaW5nIGhvdyB3ZWxsIGRhdGEgcG9pbnRzIGZpdCBpbnRvIHRoZWlyIGFzc2lnbmVkIGNsdXN0ZXJzLiBkZXRlcm1pbmluZyBob3cgd2VsbCBkYXRhIHBvaW50cyBmaXQgaW50byB0aGVpciBhc3NpZ25lZCBjbHVzdGVycy4KCmBgYHtyfQogI2F2ZXJhZ2Ugc2lsaG91ZXR0ZSBmb3IgZWFjaCBjbHVzdGVycyAKCmF2Z19zaWwgPC0gc2lsaG91ZXR0ZShrbWVhbnMucmVzdWx0JGNsdXN0ZXIsZGlzdChkYXRhX2Zvcl9jbHVzdGVyKSkgI2EgZGlzc2ltaWxhcml0eSBvYmplY3QgaW5oZXJpdGluZyBmcm9tIGNsYXNzIGRpc3Qgb3IgY29lcmNpYmxlIHRvIG9uZS4gSWYgbm90IHNwZWNpZmllZCwgZG1hdHJpeCBtdXN0IGJlLgpmdml6X3NpbGhvdWV0dGUoYXZnX3NpbCkjay1tZWFucyBjbHVzdGVyaW5nIHdpdGggZXN0aW1hdGluZyBrIGFuZCBpbml0aWFsaXphdGlvbnMKYGBgCgojIyMgQkN1YmVkIHByZWNpc2lvbiBhbmQgcmVjYWxsCgpCQ3ViZWQgcHJlY2lzaW9uIGFuZCByZWNhbGwgYXJlIG1ldHJpY3MgdXNlZCB0byBldmFsdWF0ZSB0aGUgcGVyZm9ybWFuY2Ugb2YgY2x1c3RlcmluZyBhbGdvcml0aG1zLCBwYXJ0aWN1bGFybHkgaW4gdGhlIGNvbnRleHQgb2YgZXZhbHVhdGluZyB0aGUgcXVhbGl0eSBvZiBjbHVzdGVyaW5nIGFzc2lnbm1lbnRzIGZvciBpbmRpdmlkdWFsIGRhdGEgcG9pbnRzLgoKYGBge3J9CgpjbHVzdGVyX2Fzc2lnbm1lbnRzIDwtIGMoa21lYW5zLnJlc3VsdCRjbHVzdGVyKQpncm91bmRfdHJ1dGhfbGFiZWxzIDwtIGMod2F0ZXJfcG90YWJpbGl0eSkKZGF0YSA8LSBkYXRhLmZyYW1lKGNsdXN0ZXIgPSBjbHVzdGVyX2Fzc2lnbm1lbnRzLCBsYWJlbCA9IGdyb3VuZF90cnV0aF9sYWJlbHMpCgojIEZ1bmN0aW9uIHRvIGNhbGN1bGF0ZSBCQ3ViZWQgcHJlY2lzaW9uIGFuZCByZWNhbGwKY2FsY3VsYXRlX2JjdWJlZF9tZXRyaWNzIDwtIGZ1bmN0aW9uKGRhdGEpIHsKICBuIDwtIG5yb3coZGF0YSkKICBwcmVjaXNpb25fc3VtIDwtIDAKICByZWNhbGxfc3VtIDwtIDAKCiAgZm9yIChpIGluIDE6bikgewogICAgY2x1c3RlciA8LSBkYXRhJGNsdXN0ZXJbaV0KICAgIGxhYmVsIDwtIGRhdGEkbGFiZWxbaV0KICAgIAojIENvdW50IHRoZSBudW1iZXIgb2YgaXRlbXMgZnJvbSB0aGUgc2FtZSBjYXRlZ29yeSB3aXRoaW4gdGhlIHNhbWUgY2x1c3RlcgpzYW1lX2NhdGVnb3J5X3NhbWVfY2x1c3RlciA8LSBzdW0oZGF0YSRsYWJlbFtkYXRhJGNsdXN0ZXIgPT0gY2x1c3Rlcl0gPT0gbGFiZWwpCiAgICAKIyBDb3VudCB0aGUgdG90YWwgbnVtYmVyIG9mIGl0ZW1zIGluIHRoZSBzYW1lIGNsdXN0ZXIKdG90YWxfc2FtZV9jbHVzdGVyIDwtIHN1bShkYXRhJGNsdXN0ZXIgPT0gY2x1c3RlcikKICAgIAojIENvdW50IHRoZSB0b3RhbCBudW1iZXIgb2YgaXRlbXMgd2l0aCB0aGUgc2FtZSBjYXRlZ29yeQp0b3RhbF9zYW1lX2NhdGVnb3J5IDwtIHN1bShkYXRhJGxhYmVsID09IGxhYmVsKQogICAgCiMgQ2FsY3VsYXRlIHByZWNpc2lvbiBhbmQgcmVjYWxsIGZvciB0aGUgY3VycmVudCBpdGVtIGFuZCBhZGQgdGhlbSB0byB0aGUgc3VtcwpwcmVjaXNpb25fc3VtIDwtIHByZWNpc2lvbl9zdW0gKyBzYW1lX2NhdGVnb3J5X3NhbWVfY2x1c3RlciAvdG90YWxfc2FtZV9jbHVzdGVyCnJlY2FsbF9zdW0gPC0gcmVjYWxsX3N1bSArIHNhbWVfY2F0ZWdvcnlfc2FtZV9jbHVzdGVyIC8gdG90YWxfc2FtZV9jYXRlZ29yeQogIH0KCiAgIyBDYWxjdWxhdGUgYXZlcmFnZSBwcmVjaXNpb24gYW5kIHJlY2FsbAogIHByZWNpc2lvbiA8LSBwcmVjaXNpb25fc3VtIC8gbgogIHJlY2FsbCA8LSByZWNhbGxfc3VtIC8gbgoKICByZXR1cm4obGlzdChwcmVjaXNpb24gPSBwcmVjaXNpb24sIHJlY2FsbCA9IHJlY2FsbCkpCn0KCiMgQ2FsY3VsYXRlIEJDdWJlZCBwcmVjaXNpb24gYW5kIHJlY2FsbAptZXRyaWNzIDwtIGNhbGN1bGF0ZV9iY3ViZWRfbWV0cmljcyhkYXRhKQoKIyBFeHRyYWN0IHByZWNpc2lvbiBhbmQgcmVjYWxsIGZyb20gdGhlIG1ldHJpY3MKcHJlY2lzaW9uIDwtIG1ldHJpY3MkcHJlY2lzaW9uCnJlY2FsbCA8LSBtZXRyaWNzJHJlY2FsbAoKIyBQcmludCB0aGUgcmVzdWx0cwpjYXQoIkJDdWJlZCBQcmVjaXNpb246IiwgcHJlY2lzaW9uLCAiXG4iKQpjYXQoIkJDdWJlZCBSZWNhbGw6IiwgcmVjYWxsLCAiXG4iKQoKYGBgCgojIyMgRWxib3cgbWV0aG9kCgplbGJvdyBtZXRob2QgaGVscHMgZmluZCB0aGUgb3B0aW1hbCBudW1iZXIgb2YgY2x1c3RlcnMgKGspIGluIGstbWVhbnMgY2x1c3RlcmluZy4gdGhlICJlbGJvdyIgcG9pbnQgaXMgd2hlcmUgdGhlIHJhdGUgb2YgZGVjcmVhc2UgaW4gV1NTIHNsb3dzLCBpbmRpY2F0aW5nIGEgZ29vZCBiYWxhbmNlIGJldHdlZW4gY2x1c3RlciBjb3VudCBhbmQgY2x1c3RlciBjb21wYWN0bmVzcy4gVGhlIGdvYWwgaXMgdG8gc2VsZWN0IHRoZSBzbWFsbGVzdCBrIHRoYXQgcmV0YWlucyBtb3N0IG9mIHRoZSBkYXRhJ3MgdmFyaWFiaWxpdHkuCgpgYGB7cn0KIyAzLSBFbGJvdyBtZXRob2QKI2Z2aXpfbmJjbHVzdCgpIHdpdGggd2l0aGluIGNsdXN0ZXIgc3VtcyBvZiBzcXVhcmVzICh3c3MpIG1ldGhvZCAKIApmdml6X25iY2x1c3QoZGF0YV9mb3JfY2x1c3Rlciwga21lYW5zLCBtZXRob2QgPSAid3NzIikgKwogIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IDUsIGxpbmV0eXBlID0gMikrCiAgbGFicyhzdWJ0aXRsZSA9ICJFbGJvdyBtZXRob2QiKQpgYGAKCmBgYHtyfQojIDItIHNpbGhvdWV0dGUgbWV0aG9kCiNpbnN0YWxsLnBhY2thZ2VzKCJOYkNsdXN0IikKbGlicmFyeShOYkNsdXN0KQojYSlmdml6X25iY2x1c3QoKSB3aXRoIHNpbGhvdWV0dGUgbWV0aG9kIHVzaW5nIGxpYnJhcnkoZmFjdG9leHRyYSkgCmZ2aXpfbmJjbHVzdChkYXRhX2Zvcl9jbHVzdGVyLCBrbWVhbnMsIG1ldGhvZCA9ICJzaWxob3VldHRlIikrCiAgbGFicyhzdWJ0aXRsZSA9ICJTaWxob3VldHRlIG1ldGhvZCIpCgpmcmVzLm5iY2x1c3QgPC0gTmJDbHVzdChkYXRhX2Zvcl9jbHVzdGVyLCBkaXN0YW5jZT0iZXVjbGlkZWFuIiwgbWluLm5jID0gMiwgbWF4Lm5jID0gMTAsIG1ldGhvZD0ia21lYW5zIiwgaW5kZXg9ImFsbCIpCgpgYGAKCiMjIyBUb3RhbCBXaXRoaW4tQ2x1c3RlciBTdW0gb2YgU3F1YXJlcyBmb3IgawoKV1NTIGlzIHRvIGdpdmUgeW91IGFuIGluZGljYXRpb24gb2YgaG93IHdlbGwgdGhlIGRhdGEgY2FuIGJlIHJlcHJlc2VudGVkIGJ5IGEgY2VydGFpbiBudW1iZXIgb2YgY2x1c3RlcnMuIEluIGstbWVhbnMgY2x1c3RlcmluZywgdHlwaWNhbGx5IGNob29zZSB0aGUgbnVtYmVyIG9mIGNsdXN0ZXJzIChrKSB0aGF0IG1pbmltaXplcyB0aGlzIHRvdGFsIFdTUy4KCmBgYHtyfQoKZm9yIChrIGluIDI6NSkgewogIGttZWFuc19yZXN1bHQgPC0ga21lYW5zKHdhdGVyX3BvdGFiaWxpdHksIGNlbnRlcnMgPSBrKQogIHRvdGFsX3dpdGhpbnNzIDwtIGttZWFuc19yZXN1bHQkdG90LndpdGhpbnNzCiAgY2F0KCJUb3RhbCBXaXRoaW4tQ2x1c3RlciBTdW0gb2YgU3F1YXJlcyBmb3IgayA9IiwgaywgIjoiLCB0b3RhbF93aXRoaW5zcywgIlxuIikKfQoKYGBgCgojIyMgQ29tcGFyaXNvbiBDcml0ZXJpYToKCistLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLSsKfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgQ2x1c3RyaW5nMSAgfCBDbHVzdHJpbmcyICB8IENsdXN0cmluZzMgIHwgQ2x1c3RyaW5nNCAgfAorPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09Kz09PT09PT09PT09PT0rPT09PT09PT09PT09PSs9PT09PT09PT09PT09Kz09PT09PT09PT09PT0rCnwgYXZlcmFnZSBzaWxob3VldHRlIHdpZHRoICAgICAgICAgICB8IDAuMDkgICAgICAgIHwgMC4wOCAgICAgICAgfCAwLjA4ICAgICAgICB8IDAuMDggICAgICAgIHwKKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tKwp8IHRvdGFsIHdpdGhpbi1jbHVzdGVyIHN1bSBvZiBzcXVhcmUgfCAzNTc4Mzc4NDg3NSB8IDE4MTg4MDU0ODU5IHwgMTA3NjM5MDY1MzcgfCA3MzMyNjE3NDY3ICB8CistLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLSsKfCBCQ3ViZWQgUHJlY2lzaW9uICAgICAgICAgICAgICAgICAgIHwgMC4wMDUzNDEzMTMgfCAwLjAwNTM5OTU2NSB8IDAuMDA1NDUyNTk0IHwgMC4wMDU1MDc1NDcgfAorLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0rCnwgQkN1YmVkIFJlY2FsbCAgICAgICAgICAgICAgICAgICAgICB8IDAuOTUwMDk2NSAgIHwgMC45MzM0MzM2ICAgfCAwLjkyNTI2NDQgICB8IDAuOTIwMTc1MSAgIHwKKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tKwoKQWZ0ZXIgdGVzdGluZyBhbmQgdXNpbmcgYWxsIFRoZSBzZWxlY3Rpb24gb2Ygaz01IGlzIHdlbGwtZm91bmRlZCBiYXNlZCBvbiBhIGNvbXByZWhlbnNpdmUgYW5hbHlzaXMgb2YgY2x1c3RlcmluZyBtZXRyaWNzLiBUaGUgRWxib3cgbWV0aG9kLCBhIHdpZGVseSByZWNvZ25pemVkIHRlY2huaXF1ZSwgZGlzdGluY3RseSBoaWdobGlnaHRzIGs9NSBhcyB0aGUgb3B0aW1hbCBudW1iZXIsIGRlbW9uc3RyYXRpbmcgYSBzaWduaWZpY2FudCByZWR1Y3Rpb24gaW4gd2l0aGluLWNsdXN0ZXIgdmFyaWFuY2UuIEJleW9uZCB0aGUgRWxib3cgbWV0aG9kLCBvdGhlciBjcnVjaWFsIG1ldHJpY3MgcmVpbmZvcmNlIHRoaXMgY2hvaWNlLiBUaGUgYXZlcmFnZSBzaWxob3VldHRlIHdpZHRoLCBhIG1lYXN1cmUgb2YgY2x1c3RlciBjb2hlc2lvbiBhbmQgc2VwYXJhdGlvbiwgaXMgaGlnaGVzdCBhdCAwLjA5IGZvciBrPTUsIGluZGljYXRpbmcgd2VsbC1kZWZpbmVkIGNsdXN0ZXJzLiBCQ3ViZWQgUHJlY2lzaW9uICgwLjAwNTM1MDcpIGFuZCBSZWNhbGwgKDAuOTUwMTIwOSkgY29uc2lzdGVudGx5IGZhdm9yIGs9NSwgYXR0ZXN0aW5nIHRvIHRoZSBhY2N1cmFjeSBhbmQgY29tcGxldGVuZXNzIG9mIHRoZSBjbHVzdGVycy4gRnVydGhlcm1vcmUsIHRoZSBUb3RhbCBXaXRoaW4tQ2x1c3RlciBTdW0gb2YgU3F1YXJlcyBmb3Igaz01ICg3MjYzMTUwODc2KSBpcyBub3RhYmx5IGxvd2VyLCBzaWduaWZ5aW5nIGNvbXBhY3QgYW5kIGRpc3RpbmN0IGNsdXN0ZXJzLiBUaGlzIGNvbnZlcmdlbmNlIG9mIGV2aWRlbmNlIGZyb20gdmFyaW91cyBtZXRyaWNzIHByb3ZpZGVzIGEgcm9idXN0IGp1c3RpZmljYXRpb24gZm9yIGs9NSwgZW5zdXJpbmcgdGhhdCB0aGUgcmVzdWx0aW5nIGNsdXN0ZXJzIGFyZSBib3RoIHN0YXRpc3RpY2FsbHkgc291bmQgYW5kIG1lYW5pbmdmdWwgaW4gY2FwdHVyaW5nIHRoZSB1bmRlcmx5aW5nIHN0cnVjdHVyZSBvZiB0aGUgZGF0YXNldC4KCkEgY2xhc3NpZmljYXRpb24gYXBwcm9hY2ggaXMgbW9yZSBmaXR0aW5nIGZvciB0aGUgdGFzayBvZiBkZXRlcm1pbmluZyB3YXRlciBwb3RhYmlsaXR5LiBUaGUgaW5oZXJlbnQgZGVzaWduIG9mIGNsYXNzaWZpY2F0aW9uIG1vZGVscyB0byBtYWtlIGJpbmFyeSBkZWNpc2lvbnMgYWxpZ25zIHNlYW1sZXNzbHkgd2l0aCB0aGUgZ29hbCBvZiBpZGVudGlmeWluZyB3aGV0aGVyIHdhdGVyIGlzIHNhZmUgZm9yIGNvbnN1bXB0aW9uLiBUaGlzIGZvY3VzZWQgcHJlZGljdGl2ZSBjYXBhYmlsaXR5IHByb3ZpZGVzIGFjdGlvbmFibGUgaW5zaWdodHMgY3J1Y2lhbCBmb3IgZWZmZWN0aXZlIHdhdGVyIHRyZWF0bWVudCBkZWNpc2lvbnMuIFRoZSBjbGFzc2lmaWNhdGlvbiBtb2RlbCBkaXJlY3RseSBjb21tdW5pY2F0ZXMgdGhlIHNhZmV0eSBzdGF0dXMgb2YgYSB3YXRlciBzYW1wbGUsIGFpZGluZyBpbiBhZGhlcmVuY2UgdG8gcXVhbGl0eSBzdGFuZGFyZHMuIFdoaWxlIGNsdXN0ZXJpbmcgc2VydmVzIHdlbGwgaW4gZXhwbG9yYXRvcnkgYW5hbHlzaXMsIGl0IG1pZ2h0IG5vdCBiZSBhcyBkaXJlY3RseSBhbGlnbmVkIHdpdGggdGhlIHByZWNpc2Ugb2JqZWN0aXZlIG9mIHByZWRpY3Rpbmcgd2F0ZXIgcG90YWJpbGl0eS4gSGVuY2UsIGZvciB0aGlzIHNwZWNpZmljIHRhc2ssIGEgYmluYXJ5IGNsYXNzaWZpY2F0aW9uIG1vZGVsIGlzIHJlY29tbWVuZGVkLgoKIyMjIEV2YWx1YXRpb24gYW5kIENvbXBhcmlzb24KCistLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rCnwgTWluaW5nIHRhc2sgICAgICAgIHwgQ29tcGFyaXNvbiBDcml0ZXJpYSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8Cis9PT09PT09PT09PT09PT09PT09PSs9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0rCnwgKipDbGFzc2lmaWNhdGlvbioqIHwgV2UgZXhwZXJpbWVudGVkIHdpdGggZGlmZmVyZW50IGRhdGFzZXQgc3BsaXR0aW5nIHNpemVzIHRvIGNyZWF0ZSB0aGUgZGVjaXNpb24gdHJlZSwgYW5kIGZvciBlYWNoIHNpemUsIHdlIHVzZWQgZm91ciBjbGFzc2lmaWNhdGlvbiBhbGdvcml0aG1zOiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgLSAgICoqSW5mb3JtYXRpb24gZ2FpbiAoSUQzKToqKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICFbXShJbWFnZS9DbGFzc2lmaWNhdGlvbi9pZy5wbmcpe3dpZHRoPSI1MDAifSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgIC0gICA5MCAlIHRyYWluaW5nIHNldCBhbmQgMTAlIHRlc3Rpbmcgc2V0OiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICFbXShJbWFnZS9DbGFzc2lmaWNhdGlvbi9QaWN0dXJlMS5wbmcpe3dpZHRoPSI0MDAifSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICFbXShJbWFnZS9DbGFzc2lmaWNhdGlvbi9QaWN0dXJlMS4xLnBuZyl7d2lkdGg9IjI1MCJ9ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICFbXShJbWFnZS9DbGFzc2lmaWNhdGlvbi9QaWN0dXJlMS4yLnBuZyl7d2lkdGg9IjIwMCJ9ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICFbXShJbWFnZS9DbGFzc2lmaWNhdGlvbi9QaWN0dXJlMS4zLnBuZyl7d2lkdGg9IjQ1MCJ9ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICFbXShJbWFnZS9DbGFzc2lmaWNhdGlvbi9QaWN0dXJlMS40LnBuZyl7d2lkdGg9IjQ1MCJ9ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICFbXShJbWFnZS9DbGFzc2lmaWNhdGlvbi9QaWN0dXJlMS41LnBuZyl7d2lkdGg9IjQ1MCJ9ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgIC0gICA4MCAlIHRyYWluaW5nIHNldCBhbmQgMjAlIHRlc3Rpbmcgc2V0OiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAhW10oSW1hZ2UvQ2xhc3NpZmljYXRpb24vUGljdHVyZTIucG5nKXt3aWR0aD0iNDAwIn0gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAhW10oSW1hZ2UvQ2xhc3NpZmljYXRpb24vUGljdHVyZTIuMS5wbmcpe3dpZHRoPSIyNTAifSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAhW10oSW1hZ2UvQ2xhc3NpZmljYXRpb24vUGljdHVyZTIuMi5wbmcpe3dpZHRoPSIyMDAifSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAhW10oSW1hZ2UvQ2xhc3NpZmljYXRpb24vUGljdHVyZTIuMy5wbmcpe3dpZHRoPSI0NTAifSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAhW10oSW1hZ2UvQ2xhc3NpZmljYXRpb24vUGljdHVyZTIuNC5wbmcpe3dpZHRoPSI0NTAifSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAhW10oSW1hZ2UvQ2xhc3NpZmljYXRpb24vUGljdHVyZTIuNS5wbmcpe3dpZHRoPSI0NTAifSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgIC0gICA3MCAlIHRyYWluaW5nIHNldCBhbmQgMzAlIHRlc3Rpbmcgc2V0OiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAhW10oSW1hZ2UvQ2xhc3NpZmljYXRpb24vUGljdHVyZTMucG5nKXt3aWR0aD0iNDAwIn0gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAhW10oSW1hZ2UvQ2xhc3NpZmljYXRpb24vUGljdHVyZTMuMS5wbmcpe3dpZHRoPSIyNTAifSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAhW10oSW1hZ2UvQ2xhc3NpZmljYXRpb24vUGljdHVyZTMuMi5wbmcpe3dpZHRoPSIyMDAifSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAhW10oSW1hZ2UvQ2xhc3NpZmljYXRpb24vUGljdHVyZTMuMy5wbmcpe3dpZHRoPSI0NTAifSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAhW10oSW1hZ2UvQ2xhc3NpZmljYXRpb24vUGljdHVyZTMuNC5wbmcpe3dpZHRoPSI0NTAifSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAhW10oSW1hZ2UvQ2xhc3NpZmljYXRpb24vUGljdHVyZTMuNS5wbmcpe3dpZHRoPSI0NTAifSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgLSAgICoqR2FpbiByYXRpbyAoQzQuNSk6KiogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICFbXShJbWFnZS9DbGFzc2lmaWNhdGlvbi80LjUucG5nKXt3aWR0aD0iNTAwIn0gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgIC0gICBLLWZvbGRzID0gMzogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAhW10oSW1hZ2UvQ2xhc3NpZmljYXRpb24vUGljdHVyZTQucG5nKXt3aWR0aD0iNDAwIn0gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAhW10oSW1hZ2UvQ2xhc3NpZmljYXRpb24vUGljdHVyZTQuMS5wbmcpe3dpZHRoPSIzMzAifSFbXSgpIVtdKEltYWdlL0NsYXNzaWZpY2F0aW9uL1BpY3R1cmU0LjIucG5nKXt3aWR0aD0iMjUwIn0gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAhW10oSW1hZ2UvQ2xhc3NpZmljYXRpb24vbWF0cml4LnBuZyl7d2lkdGg9IjIwMCIgaGVpZ2h0PSIxNyJ9ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAhW10oSW1hZ2UvQ2xhc3NpZmljYXRpb24vUGljdHVyZTQuMy5wbmcpe3dpZHRoPSIyNTAifSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAhW10oSW1hZ2UvQ2xhc3NpZmljYXRpb24vUGljdHVyZTQuNC5wbmcpe3dpZHRoPSI0NTAifSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgIC0gICBLLWZvbGRzID0gNTogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAhW10oSW1hZ2UvQ2xhc3NpZmljYXRpb24vUGljdHVyZTUucG5nKXt3aWR0aD0iNDAwIn0hW10oSW1hZ2UvQ2xhc3NpZmljYXRpb24vUGljdHVyZTUuMS5wbmcpe3dpZHRoPSIzMzAifSFbXShJbWFnZS9DbGFzc2lmaWNhdGlvbi9QaWN0dXJlNS4yLnBuZyl7d2lkdGg9IjIwMCJ9ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAhW10oSW1hZ2UvQ2xhc3NpZmljYXRpb24vbWF0cml4LnBuZyl7d2lkdGg9IjIyMCJ9ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAhW10oSW1hZ2UvQ2xhc3NpZmljYXRpb24vUGljdHVyZTUuMy5wbmcpe3dpZHRoPSIyNTAifSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAhW10oSW1hZ2UvQ2xhc3NpZmljYXRpb24vUGljdHVyZTUuNC5wbmcpe3dpZHRoPSI0NTAifSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgIC0gICBLLWZvbGRzID0gMTA6ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAhW10oSW1hZ2UvQ2xhc3NpZmljYXRpb24vUGljdHVyZTYucG5nKXt3aWR0aD0iNDAwIn0gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICBTaW5jZSB0aGUgdHJlZSB3YXMgZW5vcm1vdXMgYW5kIHRvIG1ha2UgaXQgbW9yZSBlYXNpbHkgYWNjZXNzaWJsZSwgd2UndmUgdXBsb2FkZWQgaXQgYXMgYSBQREYgW2ZpbGVdKGh0dHBzOi8vZHJpdmUuZ29vZ2xlLmNvbS9kcml2ZS9mb2xkZXJzLzFCLXMtVXBHYlB5UEttc1ZrUDVwOWdWZ2o5U1R6NEFSNz91c3A9c2hhcmVfbGluaykgZmlsZSBvbiBHb29nbGUgRHJpdmUuIFRoaXMgd2F5LCBpdCBjYW4gYmUgdmlld2VkIGFuZCBhbmFseXplZCBtb3JlIGVmZmljaWVudGx5LiB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICBOdW1iZXIgb2YgTGVhdmVzIDogNDM3ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICBTaXplIG9mIHRoZSB0cmVlIDogODczICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAhW10oSW1hZ2UvQ2xhc3NpZmljYXRpb24vUGljdHVyZTYuMi5wbmcpe3dpZHRoPSIyMDAifSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAhW10oSW1hZ2UvQ2xhc3NpZmljYXRpb24vUGljdHVyZTYuMS5wbmcpe3dpZHRoPSIyNzAifSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAhW10oSW1hZ2UvQ2xhc3NpZmljYXRpb24vUGljdHVyZTYuMy5wbmcpe3dpZHRoPSI0NTAifSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgLSAgICoqR2FpbiByYXRpbyAoQzUuMCk6KiogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICFbXShJbWFnZS9DbGFzc2lmaWNhdGlvbi81LjAucG5nKXt3aWR0aD0iNTAwIn0gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgIC0gICA5MCAlIHRyYWluaW5nIHNldCBhbmQgMTAlIHRlc3Rpbmcgc2V0OiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAhW10oSW1hZ2UvQ2xhc3NpZmljYXRpb24vUGljdHVyZTcucG5nKXt3aWR0aD0iMjIwIn0gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAhW10oSW1hZ2UvQ2xhc3NpZmljYXRpb24vUGljdHVyZTcuMS5wbmcpe3dpZHRoPSIyNTAifSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAhW10oSW1hZ2UvQ2xhc3NpZmljYXRpb24vUGljdHVyZTcuMi5wbmcpe3dpZHRoPSI0NTAifSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAhW10oSW1hZ2UvQ2xhc3NpZmljYXRpb24vUGljdHVyZTcuMy5wbmcpe3dpZHRoPSI0NTAifSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAhW10oSW1hZ2UvQ2xhc3NpZmljYXRpb24vUGljdHVyZTcuNC5wbmcpe3dpZHRoPSI0NTAifSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgIC0gICA4MCAlIHRyYWluaW5nIHNldCBhbmQgMjAlIHRlc3Rpbmcgc2V0OiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAhW10oSW1hZ2UvQ2xhc3NpZmljYXRpb24vUGljdHVyZTgucG5nKXt3aWR0aD0iMjIwIiBoZWlnaHQ9IjIzOCJ9ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAhW10oSW1hZ2UvQ2xhc3NpZmljYXRpb24vUGljdHVyZTguMS5wbmcpe3dpZHRoPSIyNTAifSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAhW10oSW1hZ2UvQ2xhc3NpZmljYXRpb24vUGljdHVyZTguMi5wbmcpe3dpZHRoPSI0NTAifSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAhW10oSW1hZ2UvQ2xhc3NpZmljYXRpb24vUGljdHVyZTguMy5wbmcpe3dpZHRoPSI0NTAifSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAhW10oSW1hZ2UvQ2xhc3NpZmljYXRpb24vUGljdHVyZTguNC5wbmcpe3dpZHRoPSI0NTAifSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAhW10oSW1hZ2UvQ2xhc3NpZmljYXRpb24vNS4wLnBuZyl7d2lkdGg9IjUwMCJ9ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgIC0gICA3MCAlIHRyYWluaW5nIHNldCBhbmQgMzAlIHRlc3Rpbmcgc2V0OiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAhW10oSW1hZ2UvQ2xhc3NpZmljYXRpb24vUGljdHVyZTkucG5nKXt3aWR0aD0iMjIwIn0gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAhW10oSW1hZ2UvQ2xhc3NpZmljYXRpb24vUGljdHVyZTkuMS5wbmcpe3dpZHRoPSIyNTAifSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAhW10oSW1hZ2UvQ2xhc3NpZmljYXRpb24vUGljdHVyZTkuMi5wbmcpe3dpZHRoPSI0NTAifSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAhW10oSW1hZ2UvQ2xhc3NpZmljYXRpb24vUGljdHVyZTkuMy5wbmcpe3dpZHRoPSI0NTAifSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAhW10oSW1hZ2UvQ2xhc3NpZmljYXRpb24vUGljdHVyZTkuNC5wbmcpe3dpZHRoPSI0NTAifSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgLSAgICoqR2luaSBpbmRleCAoQ0FSVCk6KiogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICFbXShJbWFnZS9DbGFzc2lmaWNhdGlvbi9naS5wbmcpe3dpZHRoPSI1MDAifSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgIC0gICA5MCAlIHRyYWluaW5nIHNldCBhbmQgMTAlIHRlc3Rpbmcgc2V0OiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAhW10oSW1hZ2UvQ2xhc3NpZmljYXRpb24vUGljdHVyZTEwLnBuZyl7d2lkdGg9IjQ1MCJ9ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAhW10oSW1hZ2UvQ2xhc3NpZmljYXRpb24vUGljdHVyZTEwLjEucG5nKXt3aWR0aD0iNDUwIn0gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAhW10oSW1hZ2UvQ2xhc3NpZmljYXRpb24vUGljdHVyZTEwLjIucG5nKXt3aWR0aD0iNDUwIn0gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAhW10oSW1hZ2UvQ2xhc3NpZmljYXRpb24vUGljdHVyZTEwLjMucG5nKXt3aWR0aD0iMjUwIn0gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAhW10oSW1hZ2UvQ2xhc3NpZmljYXRpb24vUGljdHVyZTEwLjQucG5nKXt3aWR0aD0iMjAwIn0gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAhW10oSW1hZ2UvQ2xhc3NpZmljYXRpb24vUGljdHVyZTEwLjUucG5nKXt3aWR0aD0iNDUwIn0gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgIC0gICA4MCAlIHRyYWluaW5nIHNldCBhbmQgMjAlIHRlc3Rpbmcgc2V0OiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAhW10oSW1hZ2UvQ2xhc3NpZmljYXRpb24vUGljdHVyZTExLnBuZyl7d2lkdGg9IjQ1MCJ9IVtdKEltYWdlL0NsYXNzaWZpY2F0aW9uL1BpY3R1cmUxMS4xLnBuZyl7d2lkdGg9IjQ1MCJ9ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAhW10oSW1hZ2UvQ2xhc3NpZmljYXRpb24vUGljdHVyZTExLjIucG5nKXt3aWR0aD0iNDUwIn0gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAhW10oSW1hZ2UvQ2xhc3NpZmljYXRpb24vUGljdHVyZTExLjMucG5nKXt3aWR0aD0iMjUwIn0gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAhW10oSW1hZ2UvQ2xhc3NpZmljYXRpb24vUGljdHVyZTExLjQucG5nKXt3aWR0aD0iMjAwIn0gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAhW10oSW1hZ2UvQ2xhc3NpZmljYXRpb24vUGljdHVyZTExLjUucG5nKXt3aWR0aD0iNDUwIn0gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgIC0gICA3MCAlIHRyYWluaW5nIHNldCBhbmQgMzAlIHRlc3Rpbmcgc2V0OiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAhW10oSW1hZ2UvQ2xhc3NpZmljYXRpb24vUGljdHVyZTEyLnBuZyl7d2lkdGg9IjQ1MCJ9ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAhW10oSW1hZ2UvQ2xhc3NpZmljYXRpb24vUGljdHVyZTEyLjEucG5nKXt3aWR0aD0iNDUwIn0gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAhW10oSW1hZ2UvQ2xhc3NpZmljYXRpb24vUGljdHVyZTEyLjIucG5nKXt3aWR0aD0iNDUwIn0gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAhW10oSW1hZ2UvQ2xhc3NpZmljYXRpb24vUGljdHVyZTEyLjMucG5nKXt3aWR0aD0iMjUwIn0gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAhW10oSW1hZ2UvQ2xhc3NpZmljYXRpb24vUGljdHVyZTEyLjQucG5nKXt3aWR0aD0iMjAwIn0gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAhW10oSW1hZ2UvQ2xhc3NpZmljYXRpb24vUGljdHVyZTEyLjUucG5nKXt3aWR0aD0iNDUwIn0gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CistLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rCnwgKipDbHVzdGVyaW5nKiogICAgIHwgRHVyaW5nIG91ciBleHBlcmltZW50YXRpb24sIHdlIHRlc3RlZCB3aXRoIGZpdmUgZGlmZmVyZW50IG51bWJlcnMgb2YgSyBjbHVzdGVyczogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgIVtdKEltYWdlL0NsdXN0ZXJpbmcvSy5wbmcpe3dpZHRoPSI1MDAifSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgLSAgIEsgPSAyOiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgIC0gICBDbHVzdGVyaW5nIHZpc3VhbGl6YXRpb246ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICFbXShJbWFnZS9DbHVzdGVyaW5nL1BpY3R1cmUxMy5wbmcpe3dpZHRoPSI0NTAifSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgIC0gICBDbHVzdGVyaW5nIHNhbXBsZSB2aXN1YWxpemF0aW9uOiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICFbXShJbWFnZS9DbHVzdGVyaW5nL1BpY3R1cmUxMy4xLnBuZyl7d2lkdGg9IjQ1MCJ9ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgIC0gICBEZW5kcm9ncmFtOiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICFbXShJbWFnZS9DbHVzdGVyaW5nL1BpY3R1cmUxMy4yLnBuZyl7d2lkdGg9IjQ1MCJ9ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgIC0gICBFYWNoIGNsdXN0ZXIgU2lsaG91ZXR0ZSB3aWR0aCBhbmQgc2l6ZTogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICFbXShJbWFnZS9DbHVzdGVyaW5nL1BpY3R1cmUxMy4zLnBuZyl7d2lkdGg9IjQ1MCJ9ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgIC0gICBBdmVyYWdlIFNpbGhvdWV0dGUgd2lkdGg6ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICFbXShJbWFnZS9DbHVzdGVyaW5nL1BpY3R1cmUxMy40LnBuZyl7d2lkdGg9IjQ1MCJ9ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgLSAgIEsgPSAzOiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgIC0gICBDbHVzdGVyaW5nIHZpc3VhbGl6YXRpb246ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICFbXShJbWFnZS9DbHVzdGVyaW5nL1BpY3R1cmUxNC5wbmcpe3dpZHRoPSI0NTAifSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgIC0gICBDbHVzdGVyaW5nIHNhbXBsZSB2aXN1YWxpemF0aW9uOiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICFbXShJbWFnZS9DbHVzdGVyaW5nL1BpY3R1cmUxNC4xLnBuZyl7d2lkdGg9IjQ1MCJ9ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgIC0gICBEZW5kcm9ncmFtOiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICFbXShJbWFnZS9DbHVzdGVyaW5nL1BpY3R1cmUxNC4yLnBuZyl7d2lkdGg9IjQ1MCJ9ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgIC0gICBFYWNoIGNsdXN0ZXIgU2lsaG91ZXR0ZSB3aWR0aCBhbmQgc2l6ZTogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICFbXShJbWFnZS9DbHVzdGVyaW5nL1BpY3R1cmUxNC4zLnBuZyl7d2lkdGg9IjQ1MCJ9ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgIC0gICBBdmVyYWdlIFNpbGhvdWV0dGUgd2lkdGg6ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICFbXShJbWFnZS9DbHVzdGVyaW5nL1BpY3R1cmUxNC40LnBuZyl7d2lkdGg9IjQ1MCJ9ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgLSAgIEsgPSA0OiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgIC0gICBDbHVzdGVyaW5nIHZpc3VhbGl6YXRpb246ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICFbXShJbWFnZS9DbHVzdGVyaW5nL1BpY3R1cmUxNS5wbmcpe3dpZHRoPSI0NTAifSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgIC0gICBDbHVzdGVyaW5nIHNhbXBsZSB2aXN1YWxpemF0aW9uOiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICFbXShJbWFnZS9DbHVzdGVyaW5nL1BpY3R1cmUxNS4xLnBuZyl7d2lkdGg9IjQ1MCJ9ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgIC0gICBEZW5kcm9ncmFtOiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICFbXShJbWFnZS9DbHVzdGVyaW5nL1BpY3R1cmUxNS4yLnBuZyl7d2lkdGg9IjQ1MCJ9ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgIC0gICBFYWNoIGNsdXN0ZXIgU2lsaG91ZXR0ZSB3aWR0aCBhbmQgc2l6ZTogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICFbXShJbWFnZS9DbHVzdGVyaW5nL1BpY3R1cmUxNS4zLnBuZyl7d2lkdGg9IjQ1MCIgaGVpZ2h0PSI0OCJ9ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgIC0gICBBdmVyYWdlIFNpbGhvdWV0dGUgd2lkdGg6ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICFbXShJbWFnZS9DbHVzdGVyaW5nL1BpY3R1cmUxNS40LnBuZyl7d2lkdGg9IjQ1MCJ9ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgLSAgIEsgPSA1OiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgIC0gICBDbHVzdGVyaW5nIHZpc3VhbGl6YXRpb246ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICFbXShJbWFnZS9DbHVzdGVyaW5nL1BpY3R1cmUxNi5wbmcpe3dpZHRoPSI0NTAifSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgIC0gICBDbHVzdGVyaW5nIHNhbXBsZSB2aXN1YWxpemF0aW9uOiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICFbXShJbWFnZS9DbHVzdGVyaW5nL1BpY3R1cmUxNi4xLnBuZyl7d2lkdGg9IjQ1MCJ9ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgIC0gICBEZW5kcm9ncmFtOiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICFbXShJbWFnZS9DbHVzdGVyaW5nL1BpY3R1cmUxNi4yLnBuZyl7d2lkdGg9IjQ1MCJ9ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgIC0gICBFYWNoIGNsdXN0ZXIgU2lsaG91ZXR0ZSB3aWR0aCBhbmQgc2l6ZTogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICFbXShJbWFnZS9DbHVzdGVyaW5nL1BpY3R1cmUxNi4zLnBuZyl7d2lkdGg9IjQ1MCJ9ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgIC0gICBBdmVyYWdlIFNpbGhvdWV0dGUgd2lkdGg6ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICFbXShJbWFnZS9DbHVzdGVyaW5nL1BpY3R1cmUxNi40LnBuZyl7d2lkdGg9IjQ1MCJ9ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgLSAgIE9wdGltYWwgbnVtYmVyIG9mIGNsdXN0ZXJzOiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgIC0gICBTaWxob3VldHRlIG1ldGhvZDogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICFbXShJbWFnZS9DbHVzdGVyaW5nL20xLnBuZyl7d2lkdGg9IjQ1MCJ9ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgIC0gICBCYXNlZCBvbiBtYWpvcml0eSBydWxlOiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICFbXShJbWFnZS9DbHVzdGVyaW5nL20yLnBuZyl7d2lkdGg9IjQ1MCJ9ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgIC0gICBFbGJvdyBtZXRob2Q6ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgICAgICAgICAgICAgIHwgICAgICAgICAhW10oSW1hZ2UvQ2x1c3RlcmluZy9tMy5wbmcpe3dpZHRoPSI0NTAifSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CistLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rCgojIyMgRmluZGluZ3MKCkluIHRoZSBiZWdpbm5pbmcsIHdlIHNlbGVjdGVkIGEgZGF0YXNldCB0aGF0IHJlcHJlc2VudHMgdGhlIHdhdGVyIGRhdGEgdG8gcHJlZGljdCB0aGUgcHJvYmFiaWxpdHkgb2YgZGV0ZXJtaW5pbmcgd2hldGhlciB3YXRlciBpcyBzYWZlIGZvciBjb25zdW1wdGlvbiB0byBnaXZlIHBlb3BsZSB0aGUgcHJvcGVyIG1lYXN1cmVzIHRvIGhlbHAgd2l0aCB3YXRlciB0cmVhdG1lbnQgZGVjaXNpb25zIGFuZCBlbnN1cmUgY29tcGxpYW5jZSB3aXRoIHF1YWxpdHkgc3RhbmRhcmRzLiBUbyBoYXZlIGVmZmljaWVudCwgY29ycmVjdCwgYW5kIHRoZSBiZXN0IHBvc3NpYmxlIGFjY3VyYWN5IHJlc3VsdHMsIHdlIGFwcGxpZWQgc2V2ZXJhbCBwcmVwcm9jZXNzaW5nIHRlY2huaXF1ZXMgdGhhdCBpbXByb3ZlZCB0aGUgZWZmaWNpZW5jeSBvZiB0aGUgZGF0YS4KCldlIHVzZWQgc2V2ZXJhbCBwbG90dGluZyBtZXRob2RzLCBzdWNoIGFzIGJveHBsb3RzLCBzY2F0dGVyLCBoaXN0b2dyYW1zLCBhbmQgYmFyIHBsb3RzLCB0byBpbGx1c3RyYXRlIHRoZSBkYXRhIHRvIGhlbHAgdXMgdW5kZXJzdGFuZCBvdXIgZGF0YSBhbmQgbWFrZSB0aGUgYXBwcm9wcmlhdGUgcHJlcHJvY2Vzc2luZyB0ZWNobmlxdWVzLiBCYXNlZCBvbiB0aGUgYmxvdHMgYW5kIG90aGVyIGNvbW1hbmRzLCB3ZSByZW1vdmVkIGFsbCBudWxsLCBtaXNzaW5nLCBhbmQgb3V0bGllciB2YWx1ZXMgdGhhdCBjYW4gbmVnYXRpdmVseSBhZmZlY3QgdGhlIHJlc3VsdHMuCgpBbHNvLCB3ZSBhcHBsaWVkIGRhdGEgdHJhbnNmb3JtYXRpb24sIHNvIHdlIG5vcm1hbGl6ZWQgYW5kIGRpc2NyZXRpemVkIHNvbWUgYXR0cmlidXRlcyB0byBnaXZlIHRoZW0gZXF1YWwgd2VpZ2h0IGFuZCB0byBmYWNpbGl0YXRlIGhhbmRsaW5nIHRoZSBkYXRhIGR1cmluZyBkYXRhIG1pbmluZyB0YXNrcy4gV2UgY2hlY2sgYXR0cmlidXRlIGNvcnJlbGF0aW9uIHRvIGZpbmQgcmVkdW5kYW50IGRhdGEuIFRodXMsIHdlIGFwcGxpZWQgdGhlIGRhdGEgbWluaW5nIHRhc2tzOiBDbGFzc2lmaWNhdGlvbiBhbmQgQ2x1c3RlcmluZy4KCkZvciBjbGFzc2lmaWNhdGlvbiwgd2UgdXNlIHRoZSBkZWNpc2lvbiB0cmVlIG1ldGhvZCB0byBjb25zdHJ1Y3Qgb3VyIG1vZGVsLiBXZSB0cmllZCBmb3VyIGFsZ29yaXRobXMgd2l0aCB0aHJlZSBkaWZmZXJlbnQgc2l6ZXMgZWFjaCBvZiB0cmFpbmluZyBhbmQgdGVzdGluZyBkYXRhIHRvIGdldCB0aGUgYmVzdCByZXN1bHQgZm9yIGNvbnN0cnVjdGlvbiBhbmQgZXZhbHVhdGlvbiwgYW5kIHdlIGNvbmNsdWRlZCB0aGUgZm9sbG93aW5nIHJlc3VsdHM6CgohW10oSW1hZ2UvQ2x1c3RlcmluZy9hbGwlMjBjbGFzcy5wbmcpe3dpZHRoPSI1NTAifQoKVGhlIG1vZGVsIHdpdGggdGhlIGJlc3QgYWNjdXJhY3kgd2FzIHRoZSBHYWluIHJhdGlvIGFsZ29yaXRobSB3aXRoIDEwIEstZm9sZCwgbWVhbmluZyB0aGF0IG1vc3QgdHVwbGVzIHdlcmUgY29ycmVjdGx5IGNsYXNzaWZpZWQuCgpUaGUgdHJlZSdzIHJvb3QgaXMgdGhlIFN1bGZhdGUgYXR0cmlidXRlLCB3aGljaCBoYXMgdGhlIG1heGltdW0gZW50cm9weSB0aGF0IHNwbGl0cyB0aGUgZGF0YSBpbnRvIGEgYmluYXJ5IHN1Yi10cmVlIHdoZXJlIHRoZSBmaXJzdCBub2RlIGZvciB0dXBsZXMgd2FzIFN1bGZhdGUgXDw9IFszOTYsNDQwKSwgYW5kIHRoZSBzZWNvbmQgd2FzIFN1bGZhdGUgXD4gWzM5Niw0NDApLiBUaGUgbnVtYmVyIG9mIGxlYXZlcyB3YXMgNDM3LCBhbmQgdGhlIHRyZWUgc2l6ZSB3YXMgODczLgoKRnJvbSB0aGUgcGxvdCBvZiB0aGUgW3RyZWVdKGh0dHBzOi8vZHJpdmUuZ29vZ2xlLmNvbS9maWxlL2QvMW83M1NXSENDallwNTNuSXEyM0taT0JOY1BqdkZjOEZsL3ZpZXc/dXNwPXNoYXJpbmcpLCB3ZSBjb25jbHVkZWQgdGhlIGZvbGxvd2luZyByZXN1bHRzOgoKQXMgaW5kaWNhdGVkIGJ5IHRoZSBldmFsdWF0aW9uIG1ldHJpY3MsIHRoZSBtb2RlbCdzIHBlcmZvcm1hbmNlIGRlbW9uc3RyYXRlcyBhIGhpZ2ggbGV2ZWwgb2YgYWNjdXJhY3kgb2YgOTIuMjMlLCBwcmVjaXNpb24gb2YgOTEuNjclLCBzZW5zaXRpdml0eSBvZiA5NS45NyUsIGFuZCBzcGVjaWZpY2l0eSBvZiA4Ni40MCUuIFRoZSBhY2N1cmFjeSBtZXRyaWMgcmVmbGVjdHMgdGhlIG92ZXJhbGwgY29ycmVjdG5lc3Mgb2YgdGhlIG1vZGVsJ3MgcHJlZGljdGlvbnMgYWNyb3NzIGJvdGggcG9zaXRpdmUgYW5kIG5lZ2F0aXZlIGluc3RhbmNlcy4gQSBwcmVjaXNpb24gb2YgOTEuNjclIHNpZ25pZmllcyB0aGUgcmVsaWFiaWxpdHkgb2YgdGhlIG1vZGVsIHdoZW4gcHJlZGljdGluZyBwb3NpdGl2ZSBpbnN0YW5jZXMsIGluZGljYXRpbmcgdGhhdCB0aGUgdmFzdCBtYWpvcml0eSBvZiBwb3NpdGl2ZSBwcmVkaWN0aW9ucyBhcmUgYWNjdXJhdGUuIFRoZSBoaWdoIHNlbnNpdGl2aXR5IG9mIDk1Ljk3JSBtZWFucyB0aGUgbW9kZWwncyBlZmZlY3RpdmVuZXNzIGluIGNvcnJlY3RseSBpZGVudGlmeWluZyBhIHN1YnN0YW50aWFsIHByb3BvcnRpb24gb2YgcG9zaXRpdmUgaW5zdGFuY2VzIGlzIGNydWNpYWwgaW4gc2NlbmFyaW9zIHdoZXJlIGNhcHR1cmluZyBwb3NpdGl2ZXMgaXMgYSBwcmlvcml0eS4gQWRkaXRpb25hbGx5LCB0aGUgc3BlY2lmaWNpdHkgb2YgODYuNDAlIHN1Z2dlc3RzIHRoYXQgdGhlIG1vZGVsIGlzIGFkZXB0IGF0IGNvcnJlY3RseSBpZGVudGlmeWluZyBuZWdhdGl2ZSBzYW1wbGVzLiBUaGVzZSByZXN1bHRzIGNvbGxlY3RpdmVseSBzdWdnZXN0IGEgd2VsbC1iYWxhbmNlZCBtb2RlbCB3aXRoIHN0cm9uZyBwcmVkaWN0aXZlIGNhcGFiaWxpdGllcyBhY3Jvc3MgZGlmZmVyZW50IGFzcGVjdHMgb2YgdGhlIGNsYXNzaWZpY2F0aW9uIHRhc2suCgohW10oSW1hZ2UvQ2xhc3NpZmljYXRpb24vUGljdHVyZTYuMy5wbmcpe3dpZHRoPSI0MDAifQoKQWxzbywgdGhlIHRyZWUgaWxsdXN0cmF0ZXMgdGhhdCBhbGwgYXR0cmlidXRlcyAoSGFyZG5lc3MsIFNvbGlkcywgQ2hsb3JhbWluZXMsIENvbmR1Y3Rpdml0eSwgT3JnYW5pYyBjYXJib24sIFRyaWhhbG9tZXRoYW5lcywgYW5kIFR1cmJpZGl0eSkgd2VyZSBpbnZvbHZlZCBpbiBwcmVkaWN0aW5nIHRoZSBjbGFzcyBsYWJlbC4KCkFjY29yZGluZyB0byB0aGUgbW9kZWwsIHdhdGVyIGNhbiBiZSBjb25zaWRlcmVkIHBvdGFibGUgaWYgcGFydGljdWxhciBjcml0ZXJpYSBhcmUgbWV0LiBGb3IgZXhhbXBsZSBXaGVuOgoKLSAgIFRoZSBzdWxmYXRlIGNvbmNlbnRyYXRpb24gZmFsbHMgYmVsb3cgdGhlIHJhbmdlIG9mIFszOTYsIDQ0MCkKCi0gICBUaGUgdHJpaGFsb21ldGhhbmUgY29uY2VudHJhdGlvbiBpcyBpbiB0aGUgcmFuZ2UgWzkwLCAxMDApLsKgCgotICAgVGhlIHBIIGxldmVsIGlzIHdpdGhpbiBbNywgMTEpLsKgCgotICAgVGhlIGNobG9yYW1pbmUgY29uY2VudHJhdGlvbiBmYWxscyB3aXRoaW4gdGhlIHJhbmdlIFs3LCAxMSkuCgpUaGVzZSBpbnRlcnZhbHMgcmVwcmVzZW50IHRoZSB0aHJlc2hvbGRzIG9yIGNvbmRpdGlvbnMgZXN0YWJsaXNoZWQgYnkgdGhlIGRlY2lzaW9uIHRyZWUsIGFuZCB3aGVuIHdhdGVyIHNhbXBsZXMgbWVldCB0aGVzZSBjcml0ZXJpYSwgdGhlIG1vZGVsIHByZWRpY3RzIHRoYXQgdGhlIHdhdGVyIGlzIHBvdGFibGUuCgpUaGlzIGxldmVsIG9mIGRldGFpbCBwcm92aWRlcyB2YWx1YWJsZSBpbnNpZ2h0cyBpbnRvIHRoZSBmYWN0b3JzIGNvbnRyaWJ1dGluZyB0byB3YXRlciBwb3RhYmlsaXR5IGFjY29yZGluZyB0byB0aGUgZGVjaXNpb24gdHJlZS4gSXQgYWxzbyBvZmZlcnMgYSBwcmFjdGljYWwgZ3VpZGVsaW5lIGZvciBhc3Nlc3Npbmcgd2F0ZXIgcG90YWJpbGl0eSBiYXNlZCBvbiB0aGUgc3BlY2lmaWVkIGludGVydmFscyBmb3IgU3VsZmF0ZSwgdHJpaGFsb21ldGhhbmVzLCBwSCwgYW5kIGNobG9yYW1pbmUgY29uY2VudHJhdGlvbnMuIFVzZXJzIGFuZCBzdGFrZWhvbGRlcnMgY2FuIHVzZSB0aGlzIGluZm9ybWF0aW9uIHRvIG1ha2UgaW5mb3JtZWQgZGVjaXNpb25zIGFib3V0IHRoZSBxdWFsaXR5IG9mIHdhdGVyIHNhbXBsZXMsIHV0aWxpemluZyB0aGUgZGVjaXNpb24gdHJlZSdzIGlkZW50aWZpZWQgY29uZGl0aW9ucyBhcyBhIHRvb2wgZm9yIGV2YWx1YXRpbmcgd2F0ZXIgcG9ydGFiaWxpdHkuCgpGb3IgQ2x1c3RlcmluZywgd2UgdXNlZCB0aGUgSy1tZWFucyBhbGdvcml0aG0gd2l0aCBmb3VyIGRpZmZlcmVudCBLcyB0byBmaW5kIHRoZSBvcHRpbWFsIG51bWJlciBvZiBjbHVzdGVycy4gV2UgY2FsY3VsYXRlZCB0aGUgYXZlcmFnZSBzaWxob3VldHRlIHdpZHRoIGZvciBlYWNoIGNsdXN0ZXIgYW5kIG90aGVyIG1ldHJpY3MsIGFuZCB3ZSBjb25jbHVkZWQgdGhlIGZvbGxvd2luZyByZXN1bHRzOgoKIVtdKEltYWdlL0NsdXN0ZXJpbmcvYWxsJTIwY2x1c3Rlci5wbmcpe3dpZHRoPSI1MDAifQoKVGhlIG1vZGVsIHdpdGggdGhlIG9wdGltYWwgbnVtYmVyIG9mIGNsdXN0ZXJzIGlzIEsgPSAyIHNpbmNlIGl0IGhhcyB0aGUgYmVzdCBhdmVyYWdlIHNpbGhvdWV0dGUgd2lkdGgsIG1lYW5pbmcgdGhhdCBvYmplY3RzIHdpdGhpbiB0aGUgc2FtZSBjbHVzdGVyIGFyZSBjbG9zZSB0byBlYWNoIG90aGVyIGFuZCwgYXMgZmFyIGFzIHBvc3NpYmxlLCB0byB0aGUgb2JqZWN0cyBpbiB0aGUgb3RoZXIgY2x1c3Rlci4KCiFbXShJbWFnZS9DbHVzdGVyaW5nL20xLnBuZyl7d2lkdGg9IjQwMCJ9CgpIb3dldmVyLCBhY2NvcmRpbmcgdG8gV1NTIChUb3RhbCBXaXRoaW4tQ2x1c3RlciBTdW0gb2YgU3F1YXJlcyksIHRoZSBtb2RlbCB3aXRoIHRoZSBvcHRpbWFsIG51bWJlciBvZiBjbHVzdGVycyBpcyBLID0gNSBzaW5jZSBpdCBoYXMgYSBtaW5pbWFsIFdTUy4KCiFbXShJbWFnZS9DbHVzdGVyaW5nL20zLnBuZyl7d2lkdGg9IjQwMCJ9CgpBZnRlciBjb25kdWN0aW5nIHRlc3RzIGFuZCBhbmFseXNpcywgd2UgZm91bmQgdGhhdCBvdXIgZGF0YXNldCdzIG9wdGltYWwgbnVtYmVyIG9mIGNsdXN0ZXJzIGlzIEs9NS4gV2UgdXNlZCB0aGUgRWxib3cgbWV0aG9kIGFuZCBvdGhlciBtZXRyaWNzIHN1Y2ggYXMgc2lsaG91ZXR0ZSB3aWR0aCBzY29yZSBvZiAwLjgsIEJDdWJlZCBwcmVjaXNpb24gb2YgMC4wMDU1MDc1NDcsIHJlY2FsbCBzY29yZSBvZiAwLjkyMDE3NTEsIGFuZCBUb3RhbCBXaXRoaW4tQ2x1c3RlciBTdW0gb2YgU3F1YXJlcyA3MzMyNjE3NDY3IHRvIHN1cHBvcnQgb3VyIGNvbmNsdXNpb24uCgpGaW5hbGx5LCBib3RoIG1vZGVscyBoZWxwIHByZWRpY3Qgd2hldGhlciB0aGUgd2F0ZXIgaXMgcG90YWJsZSBhbmQgYWxsb3cgdXMgdG8gcmVhY2ggb3VyIGdvYWwsIGFzc2lzdGluZyBwZW9wbGUgdG8gdGFrZSBwcmVjYXV0aW9ucyBpZiB0aGV5IHRocmVhdGVuIHRvIGdldCBwb3NpdGlvbmVkLiBIb3dldmVyLCBzaW5jZSBvdXIgZGF0YSBjb250YWlucyBhIGNsYXNzIGxhYmVsICJQb3RhYmlsaXR5LCIgdGhpcyBtYWtlcyBzdXBlcnZpc2VkIGxlYXJuaW5nIG1vZGVscyBDbGFzc2lmaWNhdGlvbiBtb3JlIGFjY3VyYXRlIGFuZCBzdWl0YWJsZSB0byBhcHBseSB0aGFuIHVuc3VwZXJ2aXNlZCBsZWFybmluZyBtb2RlbHMgQ2x1c3RlcmluZywgYXMgdGhlIGV4cGVjdGVkIG91dHB1dCBpcyBrbm93biBiZWZvcmVoYW5kLiBUaGlzIHdheSwgd2UgbWFrZSB1c2Ugb2YgdGhlIGNsYXNzIGxhYmVsIGF0dHJpYnV0ZS4KCiMjIyBSZWZlcmVuY2VzCgpbMV0gIldhdGVyIFF1YWxpdHkgYW5kIFBvdGFiaWxpdHksIsKgKkthZ2dsZSosIFNlcC4gMDQsIDIwMjMuIDxodHRwczovL3d3dy5rYWdnbGUuY29tL2RhdGFzZXRzL3VvbTE5MDM0NmEvd2F0ZXItcXVhbGl0eS1hbmQtcG90YWJpbGl0eT4KClsyXSBKLiBCcm93bmxlZSwgIk5vbi1MaW5lYXIgQ2xhc3NpZmljYXRpb24gaW4gUiB3aXRoIERlY2lzaW9uIFRyZWVzLCLCoCpNYWNoaW5lTGVhcm5pbmdNYXN0ZXJ5LmNvbSosIEF1Zy4gMjIsIDIwMTkuIDxodHRwczovL21hY2hpbmVsZWFybmluZ21hc3RlcnkuY29tL25vbi1saW5lYXItY2xhc3NpZmljYXRpb24taW4tci13aXRoLWRlY2lzaW9uLXRyZWVzLz4KClszXSAiUlB1YnMgLSBDbGFzc2lmaWNhdGlvbiBhbmQgUmVncmVzc2lvbiBUcmVlcyAoQ0FSVCkgaW4gUi4iIDxodHRwczovL3JwdWJzLmNvbS9jYW1ndWlsZC84MDMwOTY+CgpbNF0gIlJQdWJzIC0gRGF0YSBNaW5pbmc6IENsYXNzaWZpY2F0aW9uIHdpdGggRGVjaXNpb24gVHJlZXMuIiA8aHR0cHM6Ly9ycHVicy5jb20va2ptYXppZGkvMTk1NDI4PgoKWzVdIFByYWJodWRldiBLb25hbmEsICJDbGFzc2lmaWNhdGlvbiB1c2luZyBSU3R1ZGlvLCLCoCpZb3VUdWJlKiwgQXByLiAxMSwgMjAxNi4gPGh0dHBzOi8vd3d3LnlvdXR1YmUuY29tL3dhdGNoP3Y9SW1iWGRZclQ1OXM+CgpbNl1KLiBCcm93bmxlZSwgIkZlYXR1cmUgU2VsZWN0aW9uIHdpdGggdGhlIENhcmV0IFIgUGFja2FnZSwiwqAqTWFjaGluZUxlYXJuaW5nTWFzdGVyeS5jb20qLCBBdWcuIDIyLCAyMDE5LiA8aHR0cHM6Ly9tYWNoaW5lbGVhcm5pbmdtYXN0ZXJ5LmNvbS9mZWF0dXJlLXNlbGVjdGlvbi13aXRoLXRoZS1jYXJldC1yLXBhY2thZ2UvPgo=